Skip to main content

Full text of "Amiga ROM Kernel Reference Manual Devices 3rd Edition"

See other formats


AMIGA ROM Kernel 
Reference Manual 
DEVICES 





AMIGA TECHNICAL REFERENCE SERIES 
COM MODORE-AMIGA, INC. 

[a ee eee 8. EE Se re 

a | 





AMIGA 


ROM Kernel Reference Manual 


Devices 
Third Edition 


Commodore-Amiga, Inc. 


AMIGA TECHNICAL REFERENCE SERIES 


A 
vv 
Addison-Wesley Publishing Company, Inc. 


Reading, Massachusetts Menlo Park, California New York 
Don Mills, Ontario Wokingham, England Amsterdam Bonn 
Sydney Singapore Tokyo Madrid San Juan 
Paris Seoul Milan Mexico City Taipei 


Contributors: 

Dan Baker, Bruce Barrett, Mark Barton, Steve Beats, Dave Berezowski, Ray Brand, Bob Burns, Peter Cherna, Eric Cotton, Susan Dey], 
Sam Dicker, Ken Farinsky, Stuart Ferguson, Andy Finkel, Darren Greenwald, Paul Higginbottom, Larry Hildenbrand, Randell Jesup, 
David Junod, Neil Katin, Joe Katz, Kevin Klop, Adam Levin, Dave Lucas, Dale Luck, Jim Mackraz, R.J. Mical, Bryce Nesbitt, 

John Orr, Bob Pariseau, Rob Peck, Tom Pohorsky, Carl Sassenrath, Stan Shepard, Michael Sinz, Nancy Rains, Chris Raymond, 

Tom Rokicki, Jez San, Carolyn Scheppner, Leo Schwab, Darius Taghavy, Ewout Walraven, Bart Whitebook and Rob Wyesham. 


Third edition by: 
Mark Ricci 


Cover designer: 
Hannus Design Associates 


Copyright © 1991 by Commodore Electronics Limited. 


Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book and 
Addison-Wesley was aware of a trademark claim, the designations have been printed in initial caps. Amiga is a registered trademark of Commodore-Amiga, Inc. Amiga 500, 
Amiga 1000, Amiga 2000, Amiga 3000, AmigaDOS, Amiga Workbench, and Amiga Kickstart are trademarks of Commodore-Amiga, Inc. AUTOCONKHIG is a trademark of Com 
modore Electronics Limited. Commodore and the Commodore logo are registered trademarks of Commodore Electronics Limited. Motorola is a registered trademark and 
68000, 68010, 68020, 68030, and 68040 are trademarks of Motorola, Inc. CAPE and Inovatronics are trademarks of Inovatronics, Inc. Centronics is a registered trademark of Cen- 
tronics Data Computer Corp. Epson is a registered trademark of Epson America, Inc. Hewlett-Packard is a trademark and HP LaserJet is a registered trademark of Hewlett- 
Packard, Co. Hisoft and Devpac Amiga are trademarks of HiSoft. IBM is a registered trademark of International Business Machines Corp. Macintosh is a registered trademark 
of Apple Computer, Inc. UNIX is a registered trademark of AT&T. 


All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopy- 
ing, recording, or otherwise, without the prior written permission of the publisher. Printed in the United States of America. Published simultaneously in Canada. 


Commodore item number: 363099-02 


123456789-AL-9594939291 
First printing, September 1991 
ISBN 0-201-56775-X 


WARNING: The information described in this manual may contain errors or bugs, and may not function as described. All information is subject to enhancement or upgrade for 
any reason including to fix bugs, add features, or change performance. As with all software upgrades, full compatibility, although a goal, cannot be guaranteed, and is in fact 
unlikely. 


DISCLAIMER: COMMODORE-AMIGA, INC., (‘COMMODORE") MAKES NO WARRANTIES, EITHER EXPRESSED OR IMPLIED, OR REPESENTATIONS WITH RESPECT 
TO THE INFORMATION DESCRIBED HEREIN. SUCH INFORMATION IS PROVIDED ON AN “AS IS" BASIS AND IS EXPRESSLY SUBJECT TO CHANGE WITHOUT 
NOTICE. IN NO EVENT WILL COMMODORE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY 
CLAIM ARISING OUT OF THE INFORMATION PRESENTED HEREIN, EVEN IF IT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO 
NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES OR LIABILITIES FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE 
LIMITATION OR EXCLUSION MAY NOT APPLY. 


CONTENTS 


Chapter 1 INTRODUCTION TO AMIGA SYSTEM DEVICES .........................5. 1 
Wiat 18:0 DEVICE? cni3)5n uo sind vended e omeniaa ad dada ph ee Means Gs eb eoeeween Sere moemeeleess 2 
ACCESSING @ DEVICE o3 ce pisuinddiisatedn anvad evan heetaees gue et acest leaae amen adi es phananees 2 
Usingia: Devices .53 223 e'et02 shera he awde nuhwh nace pedmed aay aad eas Soe eee eee 4 
Synchronous vs. Asynchronous Requests .............. Loita nh aaah atda ae Shag earelede Race ahea Hee 5 
WO Reguést-Com pletion si oc5 cous tuntesucamscnedseunise tien Senbiashdammeyoheanteneee ees 6 
Ending Device ACCESS 3 dos daviiters denihis Sel oie ee pape nds ua wad see bade eceangeceaGinnts 7 
Devices: With Functions sieges wacastev ioe bude eddies Kei wnlende a Sepandesara de wtad aes 8 
Example Device Programs). isiisacivwen vied iteja teeta cpiei es ee SO ei ie cewteeks Les 9 

Chapter 2 AUDIO DEVICE. isif.ccii ccs says deadeaten boanedag ea tad Miawer prateadnged de 13 
About Amita Audio’. o1)4iiawesten vex tecaed nei awchbanpivewnr cada seeasaGeentaeaee anes ens 13 
Audio Device Commands and Functions .............0.. 00 cee cee eer eee cece ene eneeeneenaes 15 
Dévice Interace is 04380 valine coset eis nas daeee aeons uk New eGR EGER) Sake ce Rian 16 
Ac Simple Audio. Examples oo ysciica tas veh eas sae eile avec ale soaks bidea dawned deine 19 
Audio Allocation and Arbitration .........00... 0... c ccc cece cee cence ee en een tenn tenn eennees 21 
Allocation and Arbitration Commands ................ 0 ce cece cee e eee cnet eee nen eee e es 22 
Hardware Control Commands ..............0 06.0 cece cece eee eee eee n ee en een ene enn eeenes 25 
Double Buffered Sound Example .................. 0c cece cece cece cence eee een e eee eeeen ees 28 
Additional Information on the Audio Device ............. 06... cece cece eee ce eee een teenie ees 34 

Chapter 3 CLIPBOARD DEVICE.................... 00. cccccee cece eee e een e cece eee eeeeees 35 
Clipboard Device Commands and Functions .............. 0... c eee e cence cee e eee en eee e enn 36 
Device Interace cc aa tsraTe tee eyelet lente fi IO Used PY alien cea veut lel, Maca te 37 
Monitoring Clipboard Changes. 204i io cha.desrnavobaavnte crchaan ys. dh ereaee bad enenseadeaees 42 
Example Clipboatd Programs: .:<.00eusckeatdses deen diasekese centered eeue an pay ecieta wee eles 43 
Support Functions Called from Example Programs ................ 0. 0c cceee cece eee e eee e eee 50 
Include File for the Example Programs............ 0.0... c cece ccc e ect e eee ene e tent eee nes 58 
Additional Information on the Clipboard Device ................. ccc eee e eee e ee eee ee eenn ees 59 

Chapter 4 CONSOLE DEVICE ..............0.. 000 c ccc cece cece eee eee e tence enens 61 
Console Device Commands and Functions ................0c cece cece eee eee ee en ee neeeenees 62 
Device Interface 2.00025 vn dese ee ee ee ete eh Se tas tao 63 
About’ Console YO csc estaseta ose en gate ae au Mel cv eta nie de tnahat Mis cea maaan hese 66 
Writing to the Console Device .......... 0... c ccc cece teen een ence ence etn neeenenes 67 
Reading from the Console Device............ 0... e ccc cece cece nent e nee eee e ne ne ene enees 74 
Copy-and: Paste Support ¢226.csos plan cadci eae bean ed aed eae enue Pe 76 
Selecting Raw Input Events :..0.% cuits vec paleaae ven eave cau tated cease eats. Fesaoee 77 
Input Event RepOMs jinctvsds aoe pcawaeves venes tases ken bensgagasieessaceed ieee tenets ees 78 
Using the Console Device Without a Window ........... 06... cece cece cece nent e een ences 79 


Where Is All the Keymap Information? ............... 00 ccc c ccc c ene eee ene nee ee 81 


Console Device: Caveats co: surg he sed exans uy oe ceawe cy certs voepeseaceeeadn te taal ak es ae 81 
Console Device Example Code iacce.csuenns ciga te cestenvenh cantetinanisasseteaeer ieee) 81 
Additional Information on the Console Device ............. 0... cece ccc eect nee e eee nee eee 86 
Chapter5 GAMEPORT DEVICE ..................... 0c ccc ccc cece cece eee ne ene e eee eeeaes 87 
Gameport Device Commands and Functions .............. 0. cece eee e cece ence eee e eee n es 88 
Device Miter ace xis g copa Mande pee hoes eh neaed Coan eae eae we eae eapedeeig 89 
Gameport Events, «:.cccsies 08d dist wet dA maga e eee ween mie bob odted ven eat oles ene yes 91 
Setting and Reading the Controller Type ............ 0... c cece ccc cee eee eee e nee eee enes 94 
Joystick Example Program.............. 000s cece cece cece ee eee eee e ene ene eens tents eee 95 
Additional Information on the Gameport Device ................ 0c eee c eect eee e eee e ee eenee 100 
Chapter6 INPUT DEVICE...................ccc ccc cece eee c cece cece cece eeeneaneeeeeee 101 
Input Device Commands and Functions.............0... se cee eee e eee eee ee cece ee eee eee 102 
Device Wnterlace ss scsiass vs ess teasdiiuteoaten tun iad eevee pagans Leta ned ban saawabemea. 103 
Using the Mouse Port With the Input Device. .......... 00... cece cece ence cece ene n eee eee 107 
Adding an Input Handler ............. 2... c cece cee cee teen cence eee een ene e nese senses 108 
Writing Events to the Input Device Stream..........0.. 00. ccc ccc cece cence ene en eens 109 
Setting the Key Repeat Threshold ........... 00... cece cece cece cece eect ence eee e eee eeeeeees 112 
Setting the Key Repeat Interval ........... 0... c ccc cece ect e eee enter eee eee e teen nee n sans 113 
Determining the Current Qualifiers ......... 0.0... cece cece cece eee eee eee e beeen eee ee 113 
Input Device and Intuition ............ 00.0.0 c cece ccc cence renee net n eee e ence nee e ene 114 
Exaniple Input Device Programas. ccc.3 hacer dad ttedetian sre madcinunbues cane teeen toed pele 115 
Additional Information on the Input Device........... 0.0... cece ccc cece ee ete n eee eee ee 118 
Chapter 7 KEYBOARD DEVICE.................... ccc cece cece cece nee ee teen een e eee eees 119 
Keyboard Device Commands and Functions .............. 0.0 c cece cece eee cece een eens 120 
Device Inter ace 5.5 ceric ci doeew ees ipade ew herday co seeen cue openagee need Memaeiniadines 121 
Reading the Keyboard Matrix .......... 0.0 ccc cece eee cece een eee eee e eee e eet ene ne ees 122 
Amiga Résct- Handling cosnige stern day se dh peu hee xd eens odes Sean deee baw waness 124 
Reading Keyboard Events ........... 2... cece cece eee eect e crete ee ent eee e ene e nee e ene eee 128 
Additional Information on the Keyboard Device ............ 00... c ccc e cece cece eee eee eens 130 
Chapter 8 NARRATOR DEVICE ........................ccc ccc cece cent eee eeeneenens 131 
Narrator Device Commands and Functions ............. 0.6 c ccc eee cence ene een n eee e anes 132 
Device Interlace e.g eratiuvede tigiiawndxeras nae vo be nganse needs foes oa Qunlbenieadavm gaces 133 
Writing to the Narrator Device........... 0.00 cece cee cnn cee eect e eee teen eee e eee eee e ed 136 
Reading from the Narrator Device ............ 0... eee e ccc e eee eee eee ete e eee e tence anes 141 
How to Write Phonetically for Narrator........... 0... cece cece e eee eee eee e ence neces 143 
A More Technical Explanation .............. 0... c ccc ce ccc e eee rete cece een eee ee en sean e ed 149 
Example Speech and Mouth Movement Program.............. 0.0. cece eee e cece eect eee eee 151 
Additional Information on the Narrator Device.............. 0... cee ce ee ee eee nee eee eaes 158 
Chapter9 PARALLEL DEVICE........................ cc ccc cece cece eee e eee eeeenee teens 159 
Parallel Device Commands and Functions ................ 0. cee eee eect eter eee e eee e es 160 
Device Interfaces s.2562 5.2.5.2 fda seen Uo) alee seat oes eas Ga ee RE Se 161 
Ending A Read or Write with Termination Characters ............... 0.0 e cece eee eee e eee eee 163 


Setting Parallel Parameters ........... 0... c ccc cece cee cee cee ence eee eee ee een eeeeeeeeered 165 


Querying the Parallel Device <2 «olsen sc is ehduley daadeanae deen aapieusnniiataneewaedes 166 
Additional Information on the Parallel Device ............ 00... cece ee eee eee e rene ee eee ee ees 169 
Chapter 10 PRINTER DEVICE....................0.. 0c cose cece cece cette ence ee eeenanne 171 
Printer Device Commands and Functions .............. 000... cece eee nn cece eee eeneeeeeaees 172 
Priiter Device ACCOss. i; sets uss ec dtdas wade na Soenee aucasahtad name neue se eg weedeat ee 173 
Device Anberiace ss aid aslo neuc cailn vedere Sunde eavad RWuhg aie pet one Danaea Da ne ab aceneiins 175 
Sending Printer Commands to a Printer .......... 0.0... cece cece e eee cette ee cee eee e nee eeenee 178 
Obtaining Printer Specific Data........... 00. eee ccc cece eee eee eee e eee e eee nnn ene 181 
Reading and Changing the Printer Preferences Settings............... 0... cece ese e cece eees 182 
Ouetying the Pnnter Device 22424. o0 as fees. eek d wee Sav he beanie Doe ewes ee oneeas 186 
Error Codes from the Printer Device ......... 00.0... cece ce cee eect nee e ee eee ee enee ee ennnees 187 
Dumping a Rastport to a Printer ...... 0.0... eee een ence eect ene ene n eee. 187 
Creating a Printer Di Vers sos o72s ete ten toute sis nnd dna eee de eaten Gane em eae 196 
Example Printer Driver Source Code .......... 00... cece cece ence eee e eee ee eee e enn e ee eenn ees 210 
Additional Information on the Printer Device .............. 00. ec ce cece eee cece eee e ene eens 246 
Chapter 17.“ SCSLDEVICE sisccnecai titi 2y nestor ig ee idanslyedia eine iudsohe ieee eia eaeme 247 
SCSI Device Commands and Functions............ 000.0: cece eee e nee ee tence eee eeeen teens 248 
DIG WICS TAA Ce osc oi eis we a pte ive ra lann rmskceata oe gh a EASE RNG Sako se ee Ie 249 
DCSE DCCL sce Uae yeaah hs Sarthe NS At lat ie esc ie deelel bat 250 
RigidDiskBlock — Fields and Implementation .................... 0c sees eee eeeeen eee e eee eee 253 
PMID a BOOUSWED 45a hoatiowaaaed aki exe demeueda i wiaad ta eontoe weag iy ee renteecencrg Mee oF 257 
SCSICDINCCE Example ak. 22 iG onis ten ated ead rks cone mae aya bake oso eR Eee eae eE 260 
Additional Information on the SCSI Device............... ccc eee cece ccc e eee eee e tne neces 263 
Chapter 12 SERIAL DEVICE.......0.......... ccc c cece cece ee ence ee eee eeees 265 
Serial Device Commands and Functions ................ 0. cece ccc ee eee en ence ene eeeenneeeee 266 
DeviGe Mer lace oases acinus ealeseehals sucuua ac ba kde aaa tana ct wee eit Lagan’ 267 
A. pimple Setial Port Examines: sce scciee cs aii eediscel Suk baaeawertaensdene tartare es 269 
Altemative Modes for Serial Input or Output................ 0. cee cece eee cece ees 270 
Setting Serial Parameters (SDCMD_SETPARAMS) ............. 000 eee ee eee eeee eect eee eee 275 
Querying the Serial: Device css 524 2043 eck cocoa asd ob ee eS 278 
Sending the Break Command.............. 0. ccc ccc cece ccc e eee eee e eee n een ee nee eeneeees 279 
Error Codes from the Serial Device ............ 0... c cece cece cece ence ence ee eee eeeeeeenees 279 
Multiple Serial Port Support .......... 0... ccc ce cece cece eee e eee neeeee eens eteeseeeeanees 280 
‘Taking Over the Hardware 9:2 00506..000cataw deeds aeebiad Maaataaiiaet ian teeciwaaees oi dee 280 
Advanced Example of Serial Device Usage ................. ccc eee e eee ee eee e eee eeeeenneees 281 
Additional Information on the Serial Device .............. 00. c cece cece e eee e eee ee ene eens 284 
Chapter 13 TIMER DEVICE..........0..... 0... c ccc cece cece cece eee e ee eneeee nes 285 
Timer Device Commands and Functions .................: cece cece ence teen ee eeneeeeenn eens 286 
Device Mera Ce oe hat itea ad choy oe eacrndereder nam aurnea tet aaaseseotyuies cae bawaansenasede de 287 
SV SUCUA TUM Go atacrcernie cares weifna Sata love eed ase ed emer e Ga rane gd ase a he wewee sek kad aagsetees 290 
AUCING a Tine Request i463: b20 ses, cad uve scesecbtes uae ebinnesbewhide teeta danvabianses 292 
Using the Time Arithmetic Functions ..................ccce cece cece ccc e cece cece eeeeeeeneas 295 
E-Clock Time and Its Relationship to Actual Time ............ 0.0... cece ec eee ce eeee eee eees 298 


iii 


Example Timer Program ............ 0. cee ccc eee eee eben eee enn n ete ene n eee teenies 299 


Additional Information on the Timer Device ............ 00... cece ee eee eee erence eee e ences 302 
Chapter 14 TRACKDISK DEVICE................. 0... c cece cence tenn eens 303 
Trackdisk Device Commands and Functions ........... 00.0. e cece cece cece eee e eee eee eeeaee 304 
Device: Interface s-.:/.02. 6.0 tn a ee Pai ascii a ee a oa 305 
Advanced Commands ........... 0.0. c cece cece cece eee eee teen ne nen een enon eneneeeeees 309 
Disk Status:Commiands'....: i020) 3cves coed Gein Bile ected otto qaenerwan eetunaeasdas cas 312 
Commands for Diagnostics and Repair ......... 0.0... cece cece ence eee e eect ene e ene 314 
Notification:of Disk: Changes j..5.<00 fone cc ctugen aaaeer ec ae eee e aye sodeaanan 314 
Commands for Low-Level ACCESS ........00 0c ccc cece cece cent n cnet e ene nn eects nee eneeee 315 
Trackdisk Device. Errors 0:2 3:4 ecc coined caw edule IGE RNAs eda e od ge slea gees gee ensngiee.en 317 
Example Trackdisk Program i009 isi hited hor swnaewe teas tele Sindee tee essepead apna Lies 318 
Additional Information on the Trackdisk Device .............. 0. ccc cece cece ence eee eens 322 
Chapter: 15: “RESOURCES 3s ocr set Yds eager eae oan tae Fone e erases 323 
The: Amiga Resources. .....-s001 ce eenie kia Vllccs Seek thea Bid vousdag nga thekele 324 
Resource: Interface 0: eke eh hie eine le carer nha Sages SG eh Node ep ed 324 
BattClock Resource ivi ieia i ssine hed adrenen Adswaids Van gud honest ech daved Mead ode digea opeen tes 325 
BattMem Resource...... 0... n nent e een e ene nee seen ene neneeenes 327 
CTA RESOURCE a5 iss tnsyctovandis des dali dette a ee hee tne Laat es Sree Sod ahs ee oe cea as 328 
Disk: RESOUDCE :in3.5 cet oie eet gh he ee ee she USA ales Pas TR GRY Heme eo 336 
MileS ystemi RESOUnCE jc Shiau duties nendeaiteacyacnd Orecedectad sb eeaedlteeda tea iaue 337 
MISC@RESOUICE ics ccleet elie rahe dad eave tata ae Bab Sea iea te Aan latew iaadaales 339 
POLPO-RESOUICE. <icpesinhele Riis ccs enlace nb dig he Piensa Malad 0a esa eae Shad lites wba cairns 343 
Appendix A_ IFF: INTERCHANGE FILE FORMAT.............................0 eee ee 347 
A Quick Introduction to IFF .........0.. 00... cece ccc ccc nnn ence nen e eee n nen eneeenenes 349 
"EA IFF 85" Standard for Interchange Format Files ...........0. 00.0: cece cece een eee eens 355 
"ILBM"™ IFF Interleaved Bitniap 5.05.0 Gait ance y ndelohies eee REN a ea ha Says ies 381 
"FIX IFFE Formatted: Text 3 ss s9.6: ti ibea Gace tase eles Se Rte ee aes 393 
“SMUS" IFF Simple Musical Score:.cc.4 ees gids scan vekuleen, ii bated anes cagA es 401 
"OSV IPP 8-Bit Sampled: VOICE s:6.cicccsis sted see ba aa ea vases WR eee RL aes Sethe 419 
IFF FORM and Chunk Registry ic3:2.0505 i vigneas chicas Gv Remi oer dar adh eepeg an eoeea 429 
TIFF Source: COd@ 2: 2tscc0 23.0 ctistcec store geese a Riv tis ares Aida etelt nee Saadeh eR Roe otis 489 
Appendix B EXAMPLE DEVICE..................... 0c ccc cece cence cee e ee ene e cen e eens 557 


Appendix C AMIGA FLOPPY BOOT PROCESS AND PHYSICAL LAYOUT....... 571 


Preface 


The Amiga® Technical Reference Series is the official guide to programming Commodore’s Amiga 
computers. This revised edition of the Amiga ROM Kernel Reference Manual: Devices provides 
detailed information about the Amiga’s I/O subsystems. It has been updated for Release 2 (Kickstart 
V36 and up) of the Amiga operating system, however, most of the material and example programs 
are also compatible with version 1.3. 


This book is intended for the following audiences: 


e Novice Amiga programmers who want to try out features of the Amiga devices without writing 
full-blown applications. 


e Experienced programmers new to the Amiga. 


e Amiga programmers and developers who want to use the devices in an application. 


It is assumed that the reader can program in C or at least understand it. 
Here is a brief overview of the contents: 


Chapter 1, Introduction to Amiga System Devices. An introduction to the concept of an 
Amiga system device, the device interface, and how to perform I/O using the devices. 


Chapter 2, Audio Device. The Amiga audio device allows you to play music and make 
sounds. Two example programs are included. 


Chapter 3, Clipboard Device. The clipboard device is a central facility for sharing in- 
formation between applications. The chapter covers the types of clipboard data and the 
proper ways to use the clipboard. Two example programs are included plus an extensively 
commented module of support functions for the programs. 


Chapter 4, Console Device. The console device is the text-oriented interface for Amiga 
windows. The chapter lists the escape sequences used for console windows and the types 
of console windows. An example program is included. 


Chapter 5, Gameport Device. The gameport device manages the various pointing devices 
you plug into the mouse/joystick connectors. The chapter discusses the types of pointing 
devices, the protocol for using the device and includes an example program. 


Chapter 6, Input Device. The input device collects input event information and passes this 
on to the operating system. The chapter covers this interaction between the various input 
sources of the system, tells how to create your own input events and includes two example 
programs. 


Chapter 7, Keyboard Device. The keyboard device is the Amiga keyboard manager. The 
chapter covers how to read the keyboard at a low level and also how to program system 
reset (Ctrl-Amiga-Amiga) handlers. Three example programs are included. 


Chapter 8, Narrator Device. The narrator device is the voice of the Amiga. This chapter 
explains how to use the narrator device and the translator library, how to write phonetic 
strings for the device, and discusses the technical aspects of computer generated speech in 
thorough, but understandable terms. Two example programs are included. 


Chapter 9, Parallel Device. The parallel device manages the Amiga parallel port. Two 
example programs are included. 


Chapter 10, Printer Device. The printer device translates character streams into printer 
specific sequences. The chapter covers how to use the printer device and how to write your 
own printer driver. It contains two example programs and two complete printer drivers. 


Chapter 11, SCSI Device. The SCSI device provides the Small Computer System Interface 
forthe Amiga. The chapter covers how to send Amiga specific and SCSI specific commands 
to SCSI devices. An example program is included. 


Chapter 12, Serial Device. The serial device manages the Amiga serial port. Three 
example programs are included. 


Chapter 13, Timer Device. The timer device an interface to the Amiga’s internal clocks. 
The chapter explains the types of clocks and clock units. Four example programs are 
included. 


Chapter 14, Trackdisk Device. The trackdisk device controls the Amiga disk drives. The 
chapter covers how to use the drives at a high-level (formatted reads and writes) and 
low-level (raw reads and writes). An example program is included. 


Chapter 15, Resources. The Amiga resources are a collection of low-level interfaces to 
special Amiga hardware. The chapter covers the general resource interface and how to use 
all seven resources. Example code is included for all but one of the resources. 


Appendix A, /FF, Interchange File Format. IFF is the standardized file format of the 
Amiga. This appendix introduces IFF, covers five of the IFF types, lists the official FORM 
and Chunk names that are reserved and in use and how to register new ones. IFF include 
files, link modules, example programs and utilities are included. 


Appendix B, Example Device. This appendix contains the assembly code for an Amiga 
device for all those who want to create their own custom software I/O device. 


Appendix C, Amiga Floppy Boot Process and Physical Layout. This appendix lists the 
method used to read the boot block of a floppy and how the data is arranged in the boot 
block. 


The other manuals in this series are the Amiga User Interface Style Guide, an application design 
specification and reference work for Amiga programmers, the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs, an alphabetically organized reference of ROM function summaries and 
Amiga system include files, the Amiga ROM Kernel Reference Manual: Libraries, a work consisting 
of tutorial-style chapters on the use of each Amiga system library, and the Amiga Hardware Reference 
Manual, a detailed description of the Amiga’s hardware components. 


vi 


chapter one 
INTRODUCTION TO AMIGA 
SYSTEM DEVICES 


The Amiga system devices are software engines that provide access to the Amiga hardware. Through 
these devices, a programmer can operate a modem, spin a disk drive motor, time an event, speak to 
a user and blast a trumpet sound in beautiful, living stereo. Yet, for all that variety, the programmer 
uses each device in the same basic manner. 



















Amiga System Devices 


Introduction to Amiga System Devices 1 


What is a Device? 


An Amiga device is a software module that accepts commands and data and performs I/O operations 
based on the commands it receives. In most cases, a device interacts with either intemal or external 
hardware. Generally, an Amiga device runs as a separate task which is capable of processing your 
commands while your application attends to other things. 


Device I/O is based on the EXEC messaging system. The philosophy behind the devices is that 
I/O operations should be consistent and uniform. You print a file in the same manner as you play 
an audio sample, i.e., you send the device in question a WRITE command and the address of the 
buffer holding the data you wish to write. 


The result is that the interface presented to the programmer is essentially device independent and 
accessible from any computer language. This greatly expands the power the Amiga computer brings 
to the programmer and, ultimately, to the user. 


Devices support two types of commands: Exec standard commands like READ and WRITE, and 
device specific commands like the trackdisk device MOTOR command which controls the floppy 
drive motor. The Exec standard commands are supported by most Amiga devices. You should keep 
in mind, however, that supporting standard commands does not mean that all devices execute them 
in exactly the same manner. 


This manual contains a chapter about each of the Amiga devices. The chapters cover how you use 
a device and the commands it supports. In addition, the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs contains expanded explanations of the commands and the include files for 
each device, and the Amiga ROM Kernel Reference Manual: Libraries contains chapters on Exec. 
The command explanations list the data, flags, and other information required by a device to execute 
a command. The Exec chapters provide detailed discussions of its operation. Both are very useful 
manuals to have on your desk when you are programming the devices. 


Accessing a Device 


Accessing a device requires obtaining a message port, allocating memory for a specialized message 
packet called an I/O request, setting a pointer to the message port in the I/O request, and finally, 
establishing the link to the device itself by opening it. An example of how to do this will be provided 
later in this chapter. 


The message port is used by the device to return messages to you. A message port is obtained by 
calling the CreateMsgPort() or CreatePort() function. You must delete the message port when 
you are finished by calling the DeleteMsgPort() or DeletePort() function. 


For pre-V36 versions of the operating system (before Release 2.0), use the amiga.lib functions 
CreatePort() and DeletePort(); for V36 and higher, use the Exec functions CreateMsgPort() and 
DeleteMsgPort(). CreatePort() and DeletePort() are upward compatible, you can use them with 
V36/V37; CreateMsgPort() and DeleteMsgPort() are not backward compatible, however. 


The I/O request is used to send commands and data from your application to the device. The I/O 
request consists of fields used to hold the command you wish to execute and any parameters it 
requires. You set up the fields with the appropriate information and send it to the device by using 
Exec I/O functions. 


2 Amiga ROM Kernel Reference Manual: Devices 


At least four methods exist for creating an I/O request: 


e Declaring it as a structure. The memory required will be allocated at compile time. 


e Declaring it as a pointer and calling the AllocMem() function. You will have to call the 


FreeMem() function to release the memory when you are done. 


Declaring it as a pointer and calling the CreateExtIO() function. This function not only 
allocates the memory for the request, it also puts the message port in the I/O request. You will 
have to call the DeleteExtIO() function to delete the I/O request when you are done. This is 
the pre-V36 method (used in 1.3 and earlier versions of the operating system), but is upward 
compatible. 


Declaring it as a pointer and calling the Create[ORequest() function. This function not only 
allocates the memory for the request, it also puts the message port in the I/O request. You will 
have to call the DeleteIORequest() function to delete the I/O request when you are done. This 
is the V36/V37 method; it is not backwards compatible. 


The message port pointer in the I/O request tells the device where to respond with messages for 
your application. You must set a pointer to the message port in the I/O request if you declare it as a 
structure or allocate memory for it using AllocMem(). 


The device is opened by calling the OpenDevice() function. In addition to establishing the link to 
the device, OpenDevice() also initializes fields in the I/O request. OpenDevice() has this format: 


return = OpenDevice (device name, unit number, (struct IORequest *)IORequest, flags) 


where: 


device_name is one of the following NULL-terminated strings for system devices: 


audio.device keyboard.device serial.device 
clipboard.device narrator.device timer.device 
console.device parallel.device trackdisk.device 
gameport.device printer.device 

input.device scsi.device 


unit_number refers to one of the logical units of the device. Devices with one unit always use 
unit 0. Multiple unit devices like the trackdisk device and the timer device use the different 
units for specific purposes. The device chapters discuss the units in detail. 


IORequest is the structure discussed above. Some of the devices have their own I/O requests 
defined in their include files and others use standard I/O requests, (IOStdReq). The device 
chapters list the I/O request that each device requires. 


flags are bits set to indicate options for some of the devices. This field is set to zero for devices 
which don’t accept options when they are opened. The device chapters and autodocs list the 
flags values and uses. 


return is an indication of whether the OpenDevice() was successful with zero indicating 
success. Never assume that a device will successfully open. Check the return value and act 
accordingly. 


Zero Equals Success for OpenDevice(). | Unlike most Amiga system functions, 
OpenDevice() retums zero for success and a device-specific error value for failure. 


Introduction to Amiga System Devices 3 


Using a Device 


Once a device has been opened, you use it by passing the I/O request to it. When the device 
processes the I/O request, it acts on the information the I/O request contains and retums a reply 
message, i.e., the I/O request, to the reply port specified in the I/O request when it is finished. The 
I/O request is passed to a device using one of three functions, DoIO(), SendIO(Q) and BeginIO(Q). 
They take only one argument: the I/O request you wish to pass to the device. 


e DoIOQ is a synchronous function. It will not retum until the device has responded to the I/O 
request. 


SendIO(Q) is an asynchronous function. It can retum immediately, but the I/O operation it 
initiates may take a short or long time. Using SendIO() requires you to monitor the message 
port for a return message from the device. In addition, some devices do not actually respond 
asynchronously even though you called SendIO(); they will retum when the I/O operation is 
finished. 


BeginIO(Q is commonly used to control the quick I/O bit when sending an I/O request to a 
device. When the quick I/O flag IOF_QUICK) is set in the I/O request, a device is allowed 
to take certain shortcuts in performing and completing a request. If the request can complete 
immediately, the device will not return a reply message and the quick I/O flag will remain set. 
If the request cannot be completed immediately, the QUICK_IO flag will be clear. DoIO() 
normally requests quick I/O; SendIO(Q does not. 


DoIO(Q and SendIO(Q) are most commonly used. 


An I/O request typically has three fields set for every command sent to a device. You set the 
command itself in the io_Command field, a pointer to the data for the command in the io_Data 
field, and the length of the data in the io_Length field. 

SerialI0->10Ser.io Length = sizeof (ReadBuf fer) ; 

SerialIO->10Ser.io Data = ReadBuffer; 


SerialIO->10Ser.io Command = CMD_READ; 
SendIO((struct IORequest *)SerialIO); 


Commands consist of two parts—a prefix and the command word separated by an underscore, all 
in upper case. The prefix indicates whether the command is an Exec or device specific command. 
All Exec commands have CMD as the prefix. They are defined in the include file exec/io.h. 


Amiga Exec Commands 


CMD_CLEAR CMD_READ CMD_STOP 
CMD_FLUSH CMD_RESET CMD_WRITE 
CMD_INVALID CMD_START CMD_UPDATE 


You should not assume that a device supports all Exec commands. Always check the documentation 
before attempting to use one of them. 


Device specific command prefixes vary with the device. 


4 Amiga ROM Kernel Reference Manual: Devices 


Amiga System Device Command Prefixes and Examples 


Device Prefix Example 

Audio ADCMD ADCMD_ALLOCATE 
Clipboard CBD CBD_POST 

Console CD CD_ASKKEYMAP 
Gameport GPD GPD_SETCTYPE 
Input IND IND_SETMPORT 
Keyboard KBD KBD_READMATRIX 
Narrator no device specific commands 

Parallel PDCMD PDCMD_QUERY 
Printer PRD PRD_PRTCOMMAND 
SCSI HD HD_SCSICMD 

Serial SDCMD SDCMD_BREAK 
Timer TR TR_ADDREQUEST 
Trackdisk TD and ETD TD_MOTOR/ETD_MOTOR 


Each device maintains its own I/O request queue. When a device receives an I/O request, it either 
processes the request immediately or puts it in the queue because one is already being processed. 
After an I/O request is completely processed, the device checks its queue and if it finds another I/O 
request, begins to process that request. 


Synchronous vs. Asynchronous Requests 


As stated above, you can send I/O requests to a device synchronously or asynchronously. The 
choice of which to use is largely a function of your application. 


Synchronous requests use the DoIO() function. DoIOQ will not retum control to your application 
until the I/O request has been satisfied by the device. The advantage of this is that you don’t have 
to monitor the message port for the device reply because DoIO() takes care of all the message 
handling. The disadvantage is that your application will be tied up while the I/O request is being 
processed, and should the request not complete for some reason, DoIOQ will not return and your 
application will hang. 


Asynchronous requests use the SendIO() and BeginIO() functions. Both retum to your application 
almost immediately after you call them. This allows you to do other operations, including sending 
more I/O requests to the device. 


Do Not Touch! When you use SendIO( or BeginIOQ, the I/O request you pass to the 
device and any associated data buffers should be considered read-only. Once you send it 
to the device, you must not modify it in any way until you receive the reply message from 
the device or abort the request (though you must still wait for a reply). Any exceptions to 
this rule are documented in the autodoc for the device. 


Sending multiple asynchronous I/O requests to a device can be tricky because devices require them 
to be unique and initialized. This means you can’t use an I/O request that’s still in the queue, but 
you need the fields which were initialized in it when you opened the device. The solution is to copy 
the initialized I/O request to another I/O request(s) before sending anything to the device. 


Introduction to Amiga System Devices 5 


Regardless of what you do while you are waiting for an asynchronous I/O request to return, you 
need to have some mechanism for knowing when the request has been done. There are two basic 
methods for doing this. 


The first involves putting your application into a wait state until the device retums the I/O request 
to the message port of your application. You can use the WaitIO(), Wait() or WaitPort() function 
to wait for the return of the I/O request. 


WaitIO(Q not only waits for the return of the I/O request, it also takes care of all the message 
handling functions. This is very convenient, but you can pay for this convenience: your application 
will hang in the unlikely event that the I/O request does not retum. 


Wait() waits for a signal to be sent to the message port. It will awaken your task when the signal 
arrives, but you are responsible for all of the message handling. 


WaitPort() waits for the message port to be non-empty. It retums a pointer to the message in the 
port, but you are responsible for all of the message handling. 


The second method to detect when the request is complete involves using the CheckIO() function. 
CheckIO() takes an I/O request as its argument and returns an indication of whether or not it has 
been completed. When CheckIO() returns the completed indication, you will still have to remove 
the I/O request from the message port. 


I/O Request Completion 


A device will set the io_Error field of the I/O request to indicate the success or failure of an 
operation. The indication will be either zero for success or a non-zero error code for failure. There 
are two types of error codes: Exec I/O and device specific. Exec I/O errors are defined in the include 
file exec/errors.h; device specific errors are defined in the include file for each device. You should 
always check that the operation you requested was successful. 


The exact method for checking io_Error can depend on whether you use DoIO() or SendIO(). In 
both cases, io_Error will be set when the I/O request is returned, but in the case of DoIO(Q), the 
DoIQOQ function itself returns the same value as io_Error. 


This gives you the option of checking the function retum value: 


SerialI0->10Ser.io_ Length = sizeof (ReadBuffer); 
SerialIlO->10Ser.io Data = ReadBuffer; 
SerialIO->10Ser.io Command = CMD READ; 
if (DoIO((struct IORequest *)SerialI0); 
printf("Read failed. Error: %ld\n",SerialIO->I10Ser.io Error); 


Or you can check io_Error directly: 


SerialI0->10Ser.io Length = sizeof (ReadBuffer) ; 
SerialIO->10Ser.io Data = ReadBuffer; 
SerialIO->I10Ser.io Command = CMD READ; 
DoIO((struct IORequest *)SerialI0O); 


if (SerialIO->IOSer.io Error) 
printf ("Read failed. Error: %ld\n",SerialIO->I0Ser.io Error); 


Keep in mind that checking io_Error is the only way that I/O requests sent by SendIO() can be 
checked. 


6 Amiga ROM Kernel Reference Manual: Devices 


Testing for a failed I/O request is a minimum step, what you do beyond that depends on your 
application. In some instances, you may decide to resend the I/O request, and in others, you may 
decide to stop your application. One thing you’ll almost always want to do is to inform the user 
that an error has occurred. 


Exiting The Correct Way. If you decide that you must prematurely end your application, 
you should deallocate, release, give back and let go of everything you took to run the 
application. In other words, you should exit gracefully. 


Ending Device Access 


You end device access by reversing the steps you took to access it. This means you close the device, 
deallocate the I/O request memory and delete the message port. In that order! 


Closing a device is how you tell Exec that you are finished using a device and any associated 
resources. This can result in housecleaning being performed by the device. However, before you 
close a device, you might have to do some housecleaning of your own. 


A device is closed by calling the CloseDevice() function. The CloseDevice() function does not 
retum a value. It has this format: 


CloseDevice (IORequest) 


where I[ORequest is the I/O request used to open the device. 


You should not close a device while there are outstanding I/O requests, otherwise you can cause 
major and minor problems. Let’s begin with the minor problem: memory. If an I/O request is 
outstanding at the time you close a device, you won’t be able to reclaim the memory you allocated 
for it. 


The major problem: the device will try to respond to the I/O request. If the device tries to respond 
to an I/O request, and you’ve deleted the message port (which is covered below), you will probably 
crash the system. 


One solution would be to wait until all I/O requests you sent to the device return. This is not always 
practical if you’ve sent a few requests and the user wants to exit the application immediately. 


In that case, the only solution is to abort and remove any outstanding I/O requests. You do this with 
the functions AbortIO() and WaitIO(). They must be used together for cleaning up. AbortlO() 
will abort an I/O request, but will not prevent a reply message from being sent to the application 
requesting the abort. WaitIO(Q) will wait for an I/O request to complete and remove it from the 
message port. This is why they must be used together. 


Be Careful With AbortlO(). Do not AbortIOQ an I/O request which has not been sent 
to a device. If you do, you may crash the system. 


After the device is closed, you must deallocate the I/O request memory. The exact method you 
use depends on how you allocated the memory in the first place. For AllocMem() you call 
FreeMem(), for CreateExtIO() you call DeleteExtIO(), and for CreateIORequest() you call 
DeleteIORequest(). If you allocated the I/O request memory at compile time, you naturally have 
nothing to free. 


Introduction to Amiga System Devices 7 


Finally, you must delete the message port you created. You delete the message port by calling 
DeleteMsgPort() if you used CreateMsgPort(), or DeletePort() if you used CreatePort(). 


Here is the checklist for gracefully exiting: 

1. Abort any outstanding I/O requests with AbortlOQ) 

2. Wait for the completion of any outstanding or aborted I/O requests with WaitIO(Q). 
3. Close the device with CloseDevice(). 
4 


. Release the I/O request memory with either DeleteIORequest(), DeleteExtIO() or FreeMem() 
(as appropriate). 


5. Delete the message port with DeleteMsgPort() or DeletePort(). 


Devices With Functions 


Some devices, in addition to their commands, provide functions which can be directly called by 
applications. These functions are documented in the device specific FD files and Autodocs of the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs and the device chapters of this 
manual. 


Devices with functions behave much like Amiga libraries, i.e., you set up a base address pointer 
and call the functions as offsets from the pointer. (See the “Exec: Libraries” chapter of the Amiga 
ROM Kernel Reference Manual: Libraries.) 


The procedure for accessing a device’s functions is as follows: 


e Declare the device base address variable in the global data area. The name of the base address 
can be found in the device’s FD file. 


e Create a message port using one of the previously discussed methods if you haven’t already 
done so. 


e Create an I/O request using one of the previously discussed methods if you haven’t already 
done so. Remember to set the message port pointer in the I/O request if necessary. 


e Call OpenDevice(), passing the I/O request if you haven’t already done so. When you do 
this, the device retums a pointer to its base address in the io_Device field of the I/O request 
structure. Consult the include file for the structure you are using to determine the full name of 
the io_Device field. The base address is only valid while the device is open. 


Set the device base address variable to the pointer returned in the io_Device field. 


We will use the timer device to illustrate the above method. The name of the timer device base 
address is listed in its FD file as ““TimerBase.” 

#include <devices/timer.h> 

struct Library *TimerBase; /* device base address pointer */ 


struct MsgPort *TimerMP; /* message port pointer */ 
struct timerequest *TimerIO; /* I/O request pointer */ 


/* Create the message port */ 
if (TimerMP=CreatePort (NULL, NULL) ) 
{ 


8 Amiga ROM Kernel Reference Manual: Devices 


/* Create the I/O request */ 
if (TimerIO = (struct timerequest *) 
CreateExtIO(TimerMP, sizeof (struct timerequest) )) 
/* Open the timer device */ 
if (! (OpenDevice (TIMERNAME, UNIT MICROHZ, TimerI0,0))) 
{ 


/* Set up pointer for timer functions */ 
TimerBase = (struct Library *)TimerIO->tr_node.io Device; 


- use functions . 


/* Close the timer device */ 
CloseDevice (TimerI0O) ; 


/* Delete the I/O request */ 
DeleteExtIO(TimerI0O); 
} 


/* Delete the message port */ 
DeletePort (TimerMP) ; 
} 


Example Device Programs 


The following short programs are examples of how to use a device. Both send the serial device 
command SDCMD_QUERY to the serial device to determine the status of the serial device lines 
and registers. The first program is for pre-V36 versions of the operating system (before Release 2) 
and the second is for V36 and higher. You may use the pre-V36 version with V36 and higher, but 
you may not use the V36 version with older systems. 


The programs differ in the way they create the message port and I/O request. The pre-V36 version 
uses the amiga.lib functions CreatePort() to create the message port and CreateExtIO() to create 
the I/O request; the V36 version uses the Exec functions CreateMsgPort() to create the message 
port and CreateI[ORequest() to create the I/O request. Those are the only differences. 


DEVICE USAGE EXAMPLE (PRE-V36) 


Pre_V36_Device_Use.c 


This is an example of using the serial device. 

First, we will attempt to create a message port with CreatePort () 

Next, we will attempt to create the I/O request with CreateExtI0() 
Then, we will attempt to open the serial device with OpenDevice () 

If successful, we will send the SDCMD_QUERY command to it 

and reverse our steps. 

If we encounter an error at any time, we will gracefully exit. 


Compile with SAS C 5.10 le -cfistq -v -y -L 


Run from CLI only 
/ 


% 0 OF 0 0 OO OO 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


Introduction to Amiga System Devices 9 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#fendif 


void main(void) 

{ 

struct MsgPort *SerialMP; /* pointer to our message port */ 
struct IOExtSer *SerialI0O; /* pointer to our I/O request */ 


/* Create the message port */ 
if (SerialMP=CreatePort (NULL, NULL) ) 


/* Create the I/O request */ 
if (SerialIO = (struct IOExtSer *)CreateExtIO(SerialMP, sizeof (struct IOExtSer) )) 
{ 


/* Open the serial device */ 
if (OpenDevice (SERIALNAME, 0, (struct IORequest *)SerialI0O, OL) ) 


/* Inform user that it could not be opened */ 

printf("Error: %s did not open\n", SERIALNAME) ; 
else 

{ 

/* device opened, send query command to it */ 

SerialIO->10Ser.io Command = SDCMD_ QUERY; 

if (DoIO((struct IORequest *)SerialIO)) 


/* Inform user that query failed */ 

printf("Query failed. Error - %d\n",SerialIO->I0Ser.io Error); 
else 

/* Print serial device status - see include file for meaning */ 

printf("\n\tSerial device status: %x\n\n",SerialI0O->io Status); 


/* Close the serial device */ 
CloseDevice((struct IORequest *)SerialIO); 


} 
/* Delete the I/O request */ 
DeleteExtIO(SerialIO); 
} 
else 
/* Inform user that the I/O request could be created */ 
printf("Error: Could create I/O request\n"); 


/* Delete the message port */ 
DeletePort (SerialMP); 
} 
else 
/* Inform user that the message port could not be created */ 
printf("Error: Could not create message port\n"); 


DEVICE USAGE EXAMPLE (KICKSTART V36 AND UP) 


/* 
* V36_ Device Use.c 

* 

* This is an example of using the serial device. 

* First, we will attempt to create a message port with CreateMsgPort () 

* Next, we will attempt to create the I/O request with CreateIORequest () 
* Then, we will attempt to open the serial device with OpenDevice () 

* If successful, we will send the SDCMD_ QUERY command to it 

* and reverse our steps. 

* If we encounter an error at any time, we will gracefully exit. 

x 

* Compile with SAS C 5.10 le -cfistq -v -y -L 

* 

* Requires Kickstart V36 or greater. 

x 

* Run from CLI only 

x/ 


10 Amiga ROM Kernel Reference Manual: Devices 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


void main (void) 

{ 

struct MsgPort *SerialMP; /* pointer to our message port */ 
struct IOExtSer *SerialI0; /* pointer to our I/O request */ 


/* Create the message port */ 
if (SerialMP=CreateMsgPort () ) 
{ 


/* Create the I/O request */ 
if (SerialIO = CreateIORequest (SerialMP, sizeof (struct IOExtSer) )) 
{ 


/* Open the serial device */ 
if (OpenDevice (SERIALNAME,0, (struct IORequest *)SeriallI0, OL) ) 


/* Inform user that it could not be opened */ 

printf("Error: %s did not open\n", SERIALNAME) ; 
else 

{ 

/* device opened, send query command to it */ 

SerialI0O->10Ser.io Command = SDCMD_ QUERY; 

if (DoIO((struct IORequest *)SerialIO) ) 


/* Inform user that query failed */ 

printf("Query failed. Error - %d\n",SeriallO->1I0Ser.io Error); 
else 

/* Print serial device status - see include file for meaning */ 

printf("\n\tSerial device status: %x\n\n",SerialIO->io_ Status) ; 


/* Close the serial device */ 
CloseDevice((struct IORequest *)SerialIO); 


} 
/* Delete the I/O request */ 
DeleteIORequest (SerialIO); 
} 
else 
/* Inform user that the I/O request could be created */ 
printf("Error: Could create I/O request\n") ; 


/* Delete the message port */ 
DeleteMsgPort (SerialMP) ; 
} 


else 
/* Inform user that the message port could not be created */ 
printf("Error: Could not create message port\n"); 


Introduction to Amiga System Devices 11 


chapter two 
AUDIO DEVICE 


The Amiga has four hardware audio channels—two of the channels produce audio output from the 
left audio connector, and two from the right. These channels can be used in many ways. You can 
combine a right and a left channel for stereo sound, use a single channel, or play a different sound 
through each of the channels to create four-part harmony. 


About Amiga Audio 


Most personal computers that produce sound have hardware designed for one specific synthesis 
technique. The Amiga computer uses a very general method of digital sound synthesis that is 
quite similar to the method used in digital hi-fi components and state-of-the-art keyboard and drum 
synthesizers. 


For programs that can afford the memory, playing sampled sounds gives you a simple and very 
CPU-efficient method of sound synthesis. A sampled sound is a table of numbers which represents 
a sound digitally. When the sound is played back by the Amiga, the table is fed by a DMA 
channel into one of the four digital-to-analog converters in the custom chips. The digital-to-analog 
converter converts the samples into voltages that can be played through amplifiers and loudspeakers, 
reproducing the sound. 


On the Amiga you can create sound data in many other ways. For instance, you can use trigonometric 
functions in your programs to create the more traditional sounds—sine waves, square waves, or 
triangle waves—by using tables that describe their shapes. Then you can combine these waves 
for richer sound effects by adding the tables together. Once the data are entered, you can modify 
them with techniques described below. For information about the limitations of the audio hardware 
and suggestions for improving system efficiency and sound quality, refer to the Amiga Hardware 
Reference Manual. 


Audio Device 13 


Some commands enable your program to co-reside with other programs using the audio device 
at the same time. Programs can co-reside because the audio device handles allocation of audio 
channels and arbitrates among programs competing for the same resources. When properly used, 
this allows many programs to use the audio device simultaneously. 


The audio device commands help isolate the programmer from the idiosyncrasies of the custom 
chip hardware and make it easier to use. But you can also produce sound on the Amiga by directly 
accessing the hardware registers if you temporarily lock out other users first. For certain types of 
sound synthesis, this is more CPU-efficient. 


DEFINITIONS 


Terms used in the following discussions may be unfamiliar. Some of the more important ones are 
defined below. 


Amplitude 
The height of a waveform, which corresponds to the amount of voltage or current in the 
electronic circuit. 


Amplitude modulation 
A means of producing special audio effects by using one channel to alter the amplitude of 
another. 


Channel 
One “unit” of the audio device. 


Cycle 
One repetition of a waveform. 


Frequency 
The number of times per second a cycle repeats. 


Frequency modulation 3 
A means of producing special audio effects by using one channel to affect the period of the 
waveform produced by another channel. 


Period 
The time elapsed between the output of successive sound samples, in units of system clock 
ticks. 


Precedence 
Priority of the user of a sound channel. 


Sample 
Byte of audio data, one of the fixed-interval points on the waveform. 


Waveform 
Graph that shows a model of how the amplitude of a sound varies over time—usually over one 
cycle. 


14 Amiga ROM Kernel Reference Manual: Devices 


Audio Device Commands and Functions 


Command Operation 

ADCMD_ALLOCATE Allocate one or more of the four audio channels. 

ADCMD_FINISH Abort the current write request on one or more of the channels. 
Can be done immediately or at the end of the current cycle. 

ADCMD_FREE Free one or more audio channels. 

ADCMD_LOCK Lock one or more audio channels. 

ADCMD_PERVOL Change the period and volume for writes in progress. Can be done 


immediately or at the end of the cycle. 
ADCMD_SETPREC Set the allocation precedence of one or more channels. 
ADCMD_WAITCYCLE Wait for the current write cycle to complete on a single channel. 
Retums at the end of the cycle or immediately if no cycle is active 


on the channel. 

CMD_FLUSH Purge all write cycles and waitcycles (in-progress and queued) for 
one or more channels. 

CMD_READ Retum a pointer to the I/O block currently writing on a single 
channel. 

CMD_RESET Reset one or more channels their initialized state. All active and 
queued requests will be aborted. 

CMD_START Resume writes to one or more channels that were stopped. 

CMD_STOP Stop any write cycle in progress on one or more channels. 

CMD_WRITE Start a write cycle on a single channel. 


Exec Functions as Used in This Chapter 


AbortIOQ) Abort a command to the audio device. If in progress, it is stopped 
immediately, otherwise it is removed from the queue. 

BeginIOQ Initiate a command and return immediately (asynchronous request). 

CheckIOQ Determine the current state of an I/O request. 

CloseDevice() Relinquish use of the audio device. 

OpenDevice() Obtain use of the audio device. 

Wait() Wait for a signal from the audio device. 

WaitPort() Wait for the audio message port to receive a message. 


Exec Support Functions as Used in This Chapter 


AllocMem() Allocate a block of memory. 

CreatePort() Create a signal message port for reply messages from the audio 
device. Exec will signal a task when a message arrives at the reply 
port. 

DeletePort() Delete the message port created by CreatePort(). 

FreeMem() Free a block of previously allocated memory. 


Audio Device 15 


Device Interface 


The audio device operates like the other Amiga I/O devices. To make sound, you first open the 
audio device, then send I/O requests to it, and then close it when finished. See the “Introduction to 
Amiga System Devices” chapter for general information on device usage. 


Audio device commands use an extended I/O request block named IOAudio to send commands to 
the audio device. This is the standard [ORequest block with some extra fields added at the end. 


struct IO0Audio 
{ 


struct IORequest ioa_ Request; /* I/O request block. See exec/io.h. */ 
WORD ioa_AllocKey; /* Alloc. key filled in by audio device mf: 
UBYTE *ioa Data; /* Pointer to a sample or allocation mask */ 
ULONG ioa_Length; /* Length of sample or allocation mask. */ 
UWORD ioa Period; /* Sample playback speed */ 
UWORD ioa Volume; /* Volume of sound */ 
UWORD ioa Cycles; /* # of times to play sample. O=forever. */ 
struct Message ioa WriteMsg; /* Pilled in by device - usually not used */ 


; 


See the include file devices/audio.h for the complete structure definition. 


OPENING THE AUDIO DEVICE 


Before you can use the audio device, you must first open it with a call to OpenDevice(). Four 
primary steps are required to open the audio device: 


e Create a message port using CreatePort. Reply messages from the device must be directed to 
a message port. 


e Allocate memory for an extended I/O request structure of type IOAudio using AllocMem(). 
e Fill in io_Message.mn_ReplyPort with the message port created by CreatePort. 
e Open the audio device. Call OpenDevice(), passing IOAudio. 


struct MsgPort *AudioMP; /* Define storage for port pointer */ 
struct IOAudio *AudiolI0O; /* Define storage for IORequest pointer */ 


if (AudioMP = CreatePort (0,0) ) 
{ 


AudiolIO = (struct IOAudio *) 
AllocMem(sizeof (struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR) ; 
if (AudioI0) 


AudioMP; 


{ 
AudiolO->ioa Request.io Message.mn_ReplyPort 
0; 


AudioIO->ioa_ AllocKey 
} 


if (OpenDevice (AUDIONAME, OL, (struct IORequest *)AudioIO,0L) ) 
printf("%s did not open\n", AUDIONAME) ; 


A special feature of the OpenDevice() function with the audio device allows you to automatically 
allocate channels for your program to use when the device is opened. This is convenient since you 
must allocate one or more channels before you can produce sound. 


This is done by setting ioa_AllocKey to zero, setting ioa_Request.io_Message.mn_Node.In_Pri 
to the appropriate precedence, setting io_Data to the address of a channel combination array, and 
setting ioa_Request.ioa_Length to a non-zero value (the length of the channel combination array). 


16 Amiga ROM Kernel Reference Manual: Devices 


The audio device will attempt to allocate channels just as if you had sent the ADCMD_ALLOCATE 
command (see below). If the allocation fails, the OpenDevice(Q) call will return immediately. 


If you want to allocate channels at some later time, set the ioa_Request.ioa_Length field of the 
IOAudio block to zero when you call OpenDevice(). For more on channel allocation and the 
ADCMD_ALLOCATE command, see the section on “Allocation and Arbitration” below. 


UBYTE chans[] = {1,2,4,8}; /* get any of the four channels */ 
if (AudioI0) 
{ 


AudiolO->ioa_Request.io Message.mn_ReplyPort = AudioMP; 
Audiol0O->ioa_ AllocKey = 0; 
AudioIlO->ioa_ Request.io Message.mn_Node.1n Pri= 120; 
AudioI0O->ioa Data chans; 
AudioIO->ioa_ Length sizeof (chans) ; 
} 


if (OpenDevice (AUDIONAME, OL, (struct IORequest *)AudioIO,0L) ) 
printf("%s did not open\n", AUDIONAME) ; 


AUDIO DEVICE COMMAND TYPES 


Commands for audio use can be divided into two categories: allocation/arbitration commands and 
hardware control commands. 


There are four allocation/arbitration commands. These do not actually produce any sound. Instead 
they manage and arbitrate the audio resources for the many tasks that may be using audio in the 
Amiga’s multitasking environment. 


ADCMD_ALLOCATE - Reserves an audio channel for your program to use. 
ADCMD_FREE - Frees an audio channel. 

ADCMD_SETPREC - Changes the precedence of a sound in progress. 
ADCMD_LOCK - Tells if a channel has been stolen from you. 


The hardware control commands are used to set up, start, and stop sounds on the audio device: 


CMD_WRITE - The main command. Starts a sound playing. 

ADCMD_FINISH - Aborts a sound in progress. 

ADCMD-_PERVOL - Changes the period (speed) and volume of a sound in progress. 
CMD_FLUSH - Clears the audio channels. 

CMD_RESET - Resets and initializes the audio device. 

ADCMD_WAITCYCLE - Signals you when a cycle finishes. 

CMD_STOP - Temporarily stops a channel from playing. 

CMD_START - Restarts an audio channel that was stopped. 

CMD_READ - Retums a pointer to the current IOAudio request. 


SCOPE OF AUDIO COMMANDS 


Most audio commands can operate on multiple channels. The exceptions are 
ADCMD-_WAITCYCLE, CMD_WRITE and CMD_READ, which can only operate on one channel 
at a time. You specify the channel(s) that you want to use by setting the appropriate bits in the 
ioa_Request.io_Unit field of the IOAudio block. If you send a command for a channel that you 


do not own, your command will be ignored. For more details, see the section on “Allocation and 
Arbitration” below. 


Audio Device 17 


AUDIO AND SYSTEM I/O FUNCTIONS 


BeginiOd 


All the commands that you can give to the audio device should be sent by calling the BeginIO() 
function. This differs from other Amiga devices which generally use SendIO(Q) or DoIO(). You 
should not use SendIOQ or DoIO() with the audio device because these functions clear some 
special flags used by the audio device; this might cause audio to work incorrectly under certain 
circumstances. To be safe, you should always use BeginIO() with the audio device. 


Wait() and WaitPort() 


These functions can be used to put your task to sleep while a sound plays. Wait() takes a wake-up 
mask as its argument. The wake-up mask is usually the mp_SigBit of a MsgPort that you have set 
up to get replies back from the audio device. 


WaitPort() will put your task to sleep while a sound plays. The argument to WaitPort() is a pointer 
to a MsgPort that you have set up to get replies back from the audio device. 


Wait() and WaitPort() will not remove the message from the reply port. You must use GetMsg() 
to remove it. 


You must always use Wait() or WaitPort() to wait for I/O to finish with the audio device. 


AbortlO() 


This function can be used to cancel requests for ADCMD-ALLOCATE, ADCMD_LOCK, 
CMD_WRITE, or ADCMD_WAITCYCLE. When used with the audio device, AbortIO(Q) always 
succeeds. 


CLOSING THE AUDIO DEVICE 


An OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIOQ: 


AbortIO((struct IORequest *)AudioIO); /* Abort any pending requests */ 
WaitPort (AudioMP) ; /* Wait for abort message */ 
GetMsg (AudioMP) ; /* Get abort message */ 


CloseDevice((struct IORequest *)AudioI0); 


CloseDevice() performs an ADCMD_FREE command on any channels selected by the 
ioa_Request.io_Unit field of the IOAudio request. This means that if you close the device 
with the same IOAudio block that you used to allocate your channels (or a copy of it), the channels 
will be automatically freed. 


If you allocated channels with multiple allocation commands, you cannot use this function to 
Close all of them at once. Instead, you will have to issue one ADCMD_FREE command for each 
allocation that you made. After issuing the ADCMD_FREE commands for each of the allocations, 
you can call CloseDevice(). 


18 Amiga ROM Kernel Reference Manual: Devices 


A Simple Audio Example 


The Amiga’s audio software has a complex allocation and arbitration system which is described 
in detail in the sections below. At this point, though, it may be helpful to look at a simple audio 
example: 


/ 
Audio.c 


Audio example 


Compile with SAS C 5.10 lc -bl -cfistq -v -y -L 


% 0 0 0 OE 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <devices/audio.h> 
#include <dos/dos.h> 

#include <dos/dosextens.h> 
#include <graphics/gfxbase.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/dos protos.h> 
#include <clib/graphics_protos.h> 


#include <stdlib.h> 
#include <stdio.h> 


#ifdef LATTICE 


int CXBRK (void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#endif 


struct GfxBase *GfxBase; 


/* The whichannel array is used when we allocate a channel. */ 
/* It tells the audio device which channel we want. The code */ 
/* is 1 =channel0, 2 =channell, 4 =channel2, 8 =channel3. */ 
/* If you want more than one channel, add the codes up. x/ 
/* This array says "Give me channel 0. If it’s not available */ 
/* then try channel 1; then try channel 2 and then channel 3 */ 


UBYTE whichannel[] = { 1,2,4,8 }; 


void main(int argc, char **argv) 


{ 


struct IOAudio *Audiol0; /* Pointer to the I/O block for I/O commands */ 
struct MsgPort *AudioMP; /* Pointer to a port so the device can reply */ 
struct Message *AudioMSG; /* Pointer for the reply message */ 
ULONG device; 
BYTE *waveptr; /* Pointer to the sample bytes */ 
LONG frequency = 440; /* Frequency of the tone desired */ 
LONG duration = 3; /* Duration in seconds */ 
LONG clock = 3579545; /* Clock constant, 3546895 for PAL */ 
LONG samples = 2; /* Number of sample bytes */ 
LONG samcyc = 1; /* Number of cycles in the sample */ 
See Sasol Soo el ee oo ee eee eee tee Dose tee eee ee eee eee ee eS */ 
/* Ask the system if we are PAL or NTSC and set clock constant accordingly */ 
/* wee ww en nw we a a a we a ee ww ww He ee we ww www ew we wo wn wn nn nn eww eee ww wee nee eee x/ 


GfxBase = (struct GfxBase *)OpenLibrary ("graphics. library", OL); 
if (GfxBase == OL) 
goto killaudio; 
if (GfxBase->DisplayFlags & PAL) 
clock = 3546895; /* PAL clock */ 
else 
clock = 3579545; /* NTSC clock */ 


if (GfxBase) 
CloseLibrary((struct Library *) GfxBase) ; 


Audio Device 19 


[eoceaseceseses iS oce ue ew Behe oe Se See ce ee oe ek eS eel */ 
/* Create an audio I/O block so we can send commands to the audio device x/ 
| heletetatatatatatetatetatetatatanetatatetetatatatetaiatatatetatatatatatataatenatatatataaatatenanetatetetanenenatatenateetaneneeneaTees */ 


AudioIO = (struct IOAudio *) 
AllocMem( sizeof (struct IOAudio),MEMF_ PUBLIC | MEMF_CLEAR) ; 
if (AudioIO == 0) 
goto killaudio; 
printf ("IO block created...\n"); 


/* ie ee ea at en a eta ae ees ee ee a Se ee eee SS SO SSS SS SS x/ 
/* Create a reply port so the audio device can reply to our commands */ 
tae Se ea SS ae eee SS eo a ee Se ee eS ee ee ee ee ee ee eS */ 

AudioMP = CreatePort (0,0); 

if (AudioMP == 0) 


goto killaudio; 
printf("Port created...\n"); 


/* Set up the audio I/O block for channel allocation: x/ 
/* ioa_Request.io Message.mn_ReplyPort is the address of a reply port. */ 
/* ioa_Request.io Message.mn Node.ln Pri sets the precedence (priority) */ 
/* of our use of the audio device. Any tasks asking to use the audio */ 
/* device that have a higher precedence will steal the channel from us.*/ 
/* ioa_Request.io Command is the command field for I/O. */ 
/* ioa_Request.io Flags is used for the I/O flags. */ 
/* ioa_AllocKey will be filled in by the audio device if the allocation */ 
/* succeeds. We must use the key it gives for all other commands sent.*/ 


/* joa Data is a pointer to the array listing the channels we want. */ 
/* ioa_ Length tells how long our list of channels is. */ 
[%o---2-------~ - -- -- +--+ + + 5 + = = */ 
AudioI0O->ioa Request.io Message.mn_ReplyPort AudioMP; 

AudioIO->ioa Request.io Message.mn | Node. ln_Pri 0; 


ADCMD ALLOCATE; 


AudiolO->ioa_ Request.io Command i 
ADIOF_NOWAIT; 


Audiol0->ioa | _Request.io "Flags 
Audiol0O->ioa_AllocKey ; 
AudiolIoO- >ioa Data whichannel; 
Audiol0->ioa Length = sizeof (whichannel); 
printf("I/O block initialized for channel allocation...\n"); 


device = OpenDevice (AUDIONAME,0OL, (struct IORequest *) AudioIO ,0OL); 
if (device != 0) 

goto killaudio; 
printf("%ts opened, channel allocated...\n",AUDIONAME) ; 


/* eee we eo es ee ee ee ee x/ 
/* Create a very simple audio sample in memory. */ 
/* The sample must be CHIP RAM */ 
/* te Ss Sb i ew mS epi Se gS a sp i, dt: tJ * 
waveptr = (BYTE *)AllocMem( samples , MEMF_CHIP|MEMF_ PUBLIC); 
if (waveptr == 0) 

goto killaudio; 
waveptr[0) = 127; 
waveptr[1] = -127; 
printf("Wave data ready...\n"); 
/* ae ew wm www ww www wn ow ww ee en a a a a a wn nn ow ee */ 
/* Set up audio I/O block to play a sample using CMD_WRITE. */ 
/* The io Flags are set to ADIOF_PERVOL so we can set the */ 
/* period (speed) and volume with the our sample; x/ 
/* ioa_Data points to the sample; ioa_Length gives the length */ 
/* ioa_ Cycles tells how many times to repeat the sample */ 
/* If you want to play the sample at a given sampling rate, */ 
/* set ioa_ Period = clock/(given sampling rate) */ 
/* i, en hi a ak se sig‘, ig cgi ce mle im: pm Sao tao ts x/ 
AudiolO->ioa_ Request.io Message.mn_ ReplyPort =AudioMP; 
Audiol0O->ioa Request.io Command i =CMD_WRITE; 
AudiolO->ioa_Request.io "Flags =ADIOF_PERVOL; 
Audiol0O->ioa Data =(BYTE *)waveptr; 
AudiolO- >ioa_ Length =samples; 
AudiolO->ioa Period =clock*samcyc/ (samples* frequency) ; 
AudiolO->ioa Volume =64; 
AudiolIO->ioa Cycles =frequency*duration/samcyc; 


printf("1I/O block initialized to play tone...\n"); 


20 Amiga ROM Kernel Reference Manual: Devices 


/* Soa ao oe Seat ee at ee Ra eo eee */ 
/* Send the command to start a sound using BeginI0O() */ 
/* Go to sleep and wait for the sound to finish with */ 
/* WaitPort(). When we wake-up we have to get the reply */ 
[Bere Rae aaa ae st eae ss oe ee SSS tr */ 


printf ("Starting tone now...\n"); 
BeginIO((struct IORequest *) AudiolO ); 
WaitPort (AudioMP) ; 

AudioMSG = GetMsg (AudioMP) ; 


printf ("Sound finished...\n");- 
killaudio: 


printf("Killing audio device...\n"); 
if (waveptr != 0) 
FreeMem(waveptr, 2); 
if (device == 
CloseDevice( (struct IORequest *) AudioIO ); 
if (AudioMP != 0) 
DeletePort (AudioMP) ; 
if (AudioIO != 0) 
FreeMem( Audiol0O, sizeof (struct IOAudio) ); 
} 


Audio Allocation And Arbitration 


The first command you send to the audio device should always be ADCMD_ALLOCATE. You 
can do this when you open the device, or at a later time. You specify the channels you want in 
the ioa_Data field of the IOAudio block. If the allocation succeeds, the audio device will return 
the channels that you now own in the lower four bits of the ioa_Request.io_Unit field of your 
I1OAudio block. For instance, if the io_Unit field equals 5 (binary 0101) then you own channels 2 
and 0. If the io_Unit field equals 15 (binary 1111) then you own all the channels. 


When you send the ADCMD_ALLOCATE command, the audio device will also return a unique 
allocation key in the ioa_AllocKey of the IOAudio block. You must use this allocation key for all 
subsequent commands that you send to the audio device. The audio device uses this unique key to 
identify which task issued the command. If you do not use the correct allocation key assigned to 
you by the audio device when you send a command, your command will be ignored. 


When you request a channel with ADCMD_ALLOCATE, you specify a precedence number from 
-128 to 127 in the ioa_Request.io_Message.mn_Node.In_Pri field of the IOAudio block. If a 
channel you want is being used and you have specified a higher precedence than the current user, 
ADCMD_ALLOCATE will “steal” the channel from the other user. Later on, if your precedence 
is lower than that of another user who is performing an allocation, the channel may be stolen from 
you. 


If you set the precedence to 127 when you open the device or raise the precedence to 127 with 
the ADCMD_SETPREC command, no other tasks can steal a channel from you. When you have 
finished with a channel, you must relinquish it with the ADCMD_FREE command to make it 
available for other users. 


Audio Device 21 


The following table shows suggested precedence values. 


Suggested Precedences for Channel Allocation 


Predecence Type of Sound 
127 Unstoppable. Sounds first allocated at lower precedence, then set 
to this highest level. 
90 - 100 Emergencies. Alert, urgent situation that requires immediate action. 
80-90 Annunciators. Attention, bell (CTRL-G). 
75 Speech. Synthesized or recorded speech (narrator.device). 
50-70 Sonic cues. Sounds that provide information that is not provided 


by graphics. Only the beginning of each sound (enough to rec- 
ognize it) should be at this level; the rest should be set to sound 
effects level. 

-50 - 50 Music program. Musical notes in music-oriented program. The 
higher levels should be used for the attack portions of each note. 

-70 - -50 Sound effects. Sounds used in conjunction with graphics. More 
important sounds should use higher levels. 

-100 - -80 Background. Theme music and restartable background sounds. 


-128 Silence. Lowest level (freeing the channel completely is preferred). 


If you attempt to perform a command on a channel that has been stolen from you by a higher priority 
task, an AUDIO_NOALLOCATION error is returned and the bit in the ioa_Request.io_ Unit field 
corresponding to the stolen channel is cleared so you know which channel was stolen. 


If you want to be warmed before a channel is stolen so that you have a chance to stop your sound 
gracefully, then you should use the ADCMD_LOCK command after you open the device. This 
command is also useful for programs which write directly to the audio hardware. For more on 
ADCMD-_LOCK, see the section below. 


Allocation and Arbitration Commands 


These commands allow the audio channels to be shared among different tasks and programs. None 
of these commands can be called from interrupt code. 


ADCMD_ALLOCATE 


This command gives your program a channel to use and should be the first command you send to 
the audio device. You specify the channels you want by setting a pointer to an array in the ioa_Data 
field of the IOAudio structure. This array uses a value of 1 to allocate channel 0, 2 for channel 1, 4 
for channel 2, and 8 for channel 3. For multiple channels, add the values together. For example, if 
you want to allocate all channels, use a value of 15. 


If you want a pair of stereo channels and you have no preference about which of the left and right 
channels the system will choose for the allocation, you can pass a pointer to an array containing 3, 
5, 10, and 12. Channels 1 and 2 produce sound on the left side and channels 0 and 3 on the right 


22 Amiga ROM Kernel Reference Manual: Devices 


side. The table below shows how this array corresponds to all the possible combinations of a right 
and a left channel. 


Possible Channel Combinations 


Decimal 
Channel 3 Channel 2 Channel 1 Channel 0 Value of 
right left left right Allocation Mask 
0 0 1 1 3 
0 1 0 1 5 
1 0 1 0 10 
1 1 0 0 12 


How ADCMD_ALLOCATE Operates 


The ADCMD_ALLOCATE command tries the first combination, 3, to see if channels 0 and 1 are 
not being used. If they are available, the 3 is copied into the io_Unit field and you get an allocation 
key for these channels in the ioa_AllocKey field. You copy the key into other I/O blocks for any 
other commands you may want to perform on these channels. 


If channels 0 and 1 are being used, ADCMD_ALLOCATE tries the other combinations in tum. 
If all the combinations are in use, ADCMD_ALLOCATE checks the precedence number of the 
users of the channels and finds the combination that requires it to steal the channel or channels of 
the lowest precedence. If all the combinations require stealing a channel or channels of equal or 
higher precedence, the ADCMD_ALLOCATE request fails. Precedence is in the In_Pri field of 
the io_Message in the [OAudio block you pass to ADCMD_ALLOCATE,; it has a value from -128 
to 127. 


The ADIOF_NOWAIT Flag 


If you need to produce a sound right now and otherwise don’t want to allocate, set the 
ADIOF_NOWAIT flag to 1. This will cause the command to return an IOERR_-ALLOCFAILED 
error if it cannot allocate any of the channels. If you are producing a non-urgent sound and you can 
wait, set the ADIOF_NOWAIT flag to 0. Then, the JOAudio block returns only when you get the 
allocation. If ADIOF_NOWAIT is set to 0, the audio device will continue to retry the allocation 
request whenever channels are freed until it is successful. If the program decides to cancel the 
request, AbortIO() can be used. 


ADCMD_ALLOCATE Examples 


The following are more examples of how to tell ADCMD_ALLOCATE your channel preferences. 
If you want any channel, but want a right channel first, use an array containing 1, 8, 2, and 4: 
0001 
1000 
0010 
0100 


Audio Device 23 


If you only want a right channel, use 1 and 8 (channels 0 and 3): 
0001 
1000 


If you want only a left channel, use 2 and 4 (channels 1 and 2): 
0010 
0100 


If you want to allocate a channel and keep it for a sound that can be interrupted and restarted, 
allocate it at a certain precedence. If it is stolen, allocate it again with the ADIOF_NOWAIT flag 
set to 0. When the channel is relinquished, you will get it again. 


The Allocation Key 


If you want to perform multi-channel commands, all the channels must have the same key since 
the IOAudio block has only one allocation key field. The channels must all have that same key 
even when they were not allocated simultaneously. If you want to use a key you already have, you 
can pass that key in the ioa_AllocKey field and ADCMD_ALLOCATE can allocate other channels 
with that existing key. The ADCMD_ALLOCATE command retums a new and unique key only if 
you pass it a zero in the allocation key field. 


ADCMD_FREE 


ADCMD_FREE is the opposite of ADCMD_ALLOCATE. When you perform ADCMD_FREE 
on a channel, it does a CMD_RESET command on the hardware and “unlocks” the channel. It 
also checks to see if there are other pending allocation requests. You do not need to perform 
ADCMD_FREE on channels stolen from you. If you want channels back after they have been 
stolen, you must reallocate them with the same allocation key. 


ADCMD_SETPREC 


This command changes the precedence of an allocated channel. As an example of the use of 
ADCMD_SETPREC, assume that you are making the sound of a chime that takes a long time to 
decay. It is important that user hears the chime but not so important that he hears it decay all the way. 
You could lower precedence after the initial attack portion of the sound to let another program steal 
the channel. You can also set the precedence to maximum (127) if you do not want the channel(s) 
stolen from you. 


ADCMD_LOCK 


The ADCMD_LOCK command performs the “‘steal verify” function. When another application is 
attempting to steal a channel or channels, ADCMD_LOCK gives you a chance to clean up before the 
channel is stolen. You perform a ADCMD_LOCK command right after the ADCMD_ALLOCATE 
command. ADCMD_LOCK does not return until a higher-priority user attempts to steal the 
channel(s) or you perform an ADCMD_FREE command. If someone is attempting to steal, you 
must finish up and ADCMD_FREE the channel as quickly as possible. 


24 Amiga ROM Kernel Reference Manual: Devices 


You must use ADCMD_LOCK if you want to write directly to the hardware registers instead of using 
the device commands. If your channel is stolen, you are not notified unless the ADCMD_LOCK 
command is present. This could cause problems for the task that has stolen the channel and is now 
using it at the same time as your task. ADCMD_LOCK sets a switch that is not cleared until you 
perform an ADCMD_FREE command on the channel. Canceling an ADCMD_LOCK request with 
AbortIOQ will not free the channel. 


The following outline describes how ADCMD_LOCK works when a channel is stolen and when it 
is not stolen. 


1. User A allocates a channel. 
2. User A locks the channel. 
If User B allocates the channel with a higher precedence: 


3. User B’s ADCMD_ALLOCATE command is suspended (regardless of the setting of the 
ADIOF_NOWAIT flag). 


4. User A’s lock command is replied to with an error (ADIOERR_-CHANNELSTOLEN). 
5. User A does whatever is needed to finish up when a channel is stolen. 

6. User A frees the channel with ADCMD_FREE. 

7. User B’s ADCMD_ALLOCATE command is replied to. Now user B has the channel. 
If the channel is not allocated by another user: 

3. User A finishes the sound. 

4. User A performs the ADCMD_FREE command. 

5. User A’s ADCMD_LOCK command is replied to. 


Never make the freeing of a channel (if the channel is stolen) dependent on allocating another 
channel. This may cause a deadlock. If you want channels back after they have been stolen, you 
must reallocate them with the same allocation key. To keep a channel and never let it be stolen, set 
precedence to maximum (127). Do not use a lock for this purpose. 


Hardware Control Commands 


The following commands change hardware registers and affect the actual sound output. 


CMD_WRITE 


This is a single-channel command and is the main command for making sounds. You pass the 
following to CMD_WRITE: 


e A pointer to the waveform to be played (must start on a word boundary and must be in memory 
accessible by the custom chips, MEMF_CHIP) 


e The length of the waveform in bytes (must be an even number) 
e Account of how many times you want to play the waveform 


Audio Device 25 


If the count is 0, CMD_WRITE will play the waveform from beginning to end, then repeat the 
waveform continuously until something aborts it. 


If you want period and volume to be set at the start of the sound, set the WRITE command’s 
ADIOF_PERVOL flag. If you do not do this, the previous volume and period for that channel will 
be used. This is one of the flags that is cleared by DoIO() and SendIO(). The ioa_WriteMsg field in 
the IOAudio block is an extra message field that can be replied to at the start of the CMD_WRITE. 
This second message is used only to tell you when the CMD_WRITE command starts processing, 
and it is used only when the ADIOF_WRITEMESSAGE flag is set to 1. 


If a CMD_STOP has been performed, the CMD_WRITE requests are queued up. The 
CMD_WRITE command does not make its own copy of the waveform, so any modification of 
the waveform before the CMD_WRITE command is finished may affect the sound. This is some- 
times desirable for special effects. To splice together two waveforms without clicks or pops, you 
must send a separate, second CMD_WRITE command while the first is still in progress. This 
technique is used in double-buffering, which is described below. 


By using two waveform buffers and two CMD_WRITE requests you can compute a waveform 
continuously. This is called double-buffering. The following describes how you use double- 
buffering. 

. Compute a waveform in memory buffer A. 

. Issue CMD_WRITE A with io_Data pointing to buffer A. 

. Continue the waveform in memory buffer B. 

. Issue CMD_WRITE B with io_Data pointing to Buffer B. 

. Wait for CMD_WRITE A to finish. 

. Continue the waveform in memory buffer A. 

. Issue CMD_WRITE A with io_Data pointing to Buffer A. 

. Wait for CMD_WRITE B to finish. 

. Loop back to step 3 until the waveform is finished. 

. At the end, remember to wait until both CMD_WRITE A and B are finished. 


Oo ON KD nN fF W NY 


— 
oS 


ADCMD_FINISH 


The ADCMD_FINISH command aborts (calls AbortIO()) the current write request on a channel 
or channels. This is useful if you have something playing, such as a long buffer or some repetitions 
of a buffer, and you want to stop it. 


ADCMD_FINISH has a flag you can set (ADIOF_SYNCCY CLE) that allows the waveform to finish 
the current cycle before aborting it. This is useful for splicing together sounds at zero crossings or 
some other place in the waveform where the amplitude at the end of one waveform matches the 
amplitude at the beginning of the next. Zero crossings are positions within the waveform at which 
the amplitude is zero. Splicing at zero crossings gives you fewer clicks and pops when the audio 
channel is turned off or the volume is changed. 


26 Amiga ROM Kernel Reference Manual: Devices 


ADCMD_PERVOL 


ADCMD_PERVOL lets you change the volume and period of a CMD_WRITE that is in progress. 
The change can take place immediately or you can set the ADIOF_SYNCCYCLE flag to have the 
change occur at the end of the cycle. This is useful to produce vibratos, glissandos, tremolos, and 
volume envelopes in music or to change the volume of a sound. 


CMD_FLUSH 


CMD_FLUSH aborts (calls AbortIO(Q)) all CMD_WRITEs and all ADCMD_WAITCYCLEs 
that are queued up for the channel or channels. It does not abort ADCMD_LOCKs (only 
ADCMD-_FREE clears locks). 


CMD_RESET 


CMD_RESET restores all the audio hardware registers. It clears the attach bits, restores the 
audio interrupt vectors if the programmer has changed them, and performs the CMD_FLUSH 
command to cancel all requests to the channels. CMD_RESET also unstops channels that have had 
a CMD_STOP performed on them. CMD_RESET does not unlock channels that have been locked 
by ADCMD_LOCK. 


ADCMD_WAITCYCLE 


This is a single-channel command. ADCMD_WAITCYCLE is replied to when the current cycle 
has completed, If there is no CMD_WRITE in progress, it retums immediately. 


CMD_STOP 


This command stops the current write cycle immediately. If there are no CMD_WRITESs in progress, 
it sets a flag so any future CMD_WRITEs are queued up and do not begin processing (playing). 


CMD_START 


CMD_START undoes the CMD_STOP command. Any cycles that were stopped by the 
CMD_STOP command are actually lost because of the impossibility of determining exactly where 
the DMA ceased. If the CMD_WRITE command was playing two cycles and the first one was 
playing when CMD_STOP was issued, the first one is lost and the second one will be played. 


This command is also useful when you are playing the same wave form with the same period out 
of multiple channels. If the channels are stopped when the CMD_WRITE commands are issued, 
CMD_START exactly synchronizes them, avoiding cancellation and distortion. When channels are 
allocated, they are effectively started by the CMD_START command. 


CMD_READ 


CMD_READ is a single-channel command. Its only function is to retum a pointer to the current 
CMD_WRITE command. It enables you to determine which request is being processed. 


Audio Device 27 


Double Buffered Sound Example 


The program listed below demonstrates double buffering with the audio device. Run the program 
from the CLI. It takes one parameter—the name of an IFF 8SVX sample file to play on the Amiga’s 
audio device. The maximum size for a sample on the Amiga is 128K. However, by using double- 
buffering and queueing up requests to the audio device, you can play longer samples smoothly and 
without breaks. 


/* 
* Audio 8SVX.c 

* 

* 8SVX example - double buffers >128K samples 

* 

* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 
* 

* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <devices/audio.h> 
#include <dos/dos.h> 

#include <dos/dosextens.h> 
#include <graphics/gfxbase.h> 
#include <iff/iff.h> 

#include <iff/8svx.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/dos protos.h> 
#include <clib/graphics protos.h> 


#include <stdlib.h> 
#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#fendif 


#define VHDR MakeID(’V’,’H’,’D’,’R’) 
#define BODY MakeID(’B’,’0’,’D’,’Y’) 
#define MY8S MakeID('8’,’S’,’V’,'X") 


void kill8svx(char *); 
void kill8 (void); 
| eke ereaiectetatetatatatatetatatatatatel */ /* These globals are needed */ 
/* GLOBALS */ /* by the clean up routines */ 
[PoSesseseut cect see cns */ 
struct IOAudio *AIOptril, /* Pointers to Audio IOBs */ 
*AlIOptr2, 
*Aptr; 
struct Message *msg; /* Msg, port and device for */ 
struct MsgPort *port, /* driving audio */ 
*portl, *port2; 
ULONG device; 
UBYTE *sbase, *fbase; /* For sample memory allocation */ 
ULONG fsize,ssize; /* and freeing */ 


struct FileHandle ‘*v8handle; 


UBYTE chanl{] = { 1 }; /* Audio channel allocation arrays */ 

UBYTE chan2[] = { 2 }; 

UBYTE chan3[] = { 4 }; 

UBYTE chan4{] = { 8 }; 

UBYTE *chans[] = {chanl, chan2, chan3,chan4}; 

BYTE oldpri,c; /* Stuff for bumping priority */ 
struct Task *mt=0L; 
struct GfxBase *GfxBase = NULL; 


28 Amiga ROM Kernel Reference Manual: Devices 


[see see eee */ 
/* MAIN */ 
[¥eeeen */ 


*/ 
*/ 


/*------------- x/ 

/* LOCALS */ 

/*------------- x/ 
char *fname; /* File name and data pointer*/ 
UBYTE *p8data; /* for file read. */ 
ULONG clock; /* Clock constant x/ 
ULONG length[2]; /* Sample lengths x/ 
BYTE iobuffer[8], /* Buffer for 8SVX header x/ 

*psample[2]); /* Sample pointers */ 

Chunk *p8Chunk; /* Pointers for 8SVX parsing */ 
Voice8Header *pVoice8Header; 
ULONG y, rd8count, speed; /* Counters, sampling speed 
ULONG wakebit; /* BR wakeup mask 

/*------------- */ 

/* CODE x/ 

[*------------- x/ 

$oSe ate eee OS eee x/ 

/* Check Arguments, Initialize */ 

koe ee en ee eee x/ 

fbhase=0L; 

sbase=0L; 


AIOptr1=0L; 
AlOptr2=0L; 
port=0L; 
port1=0L; 
port2=0L; 
v8handle=0L; 
device=1L; 


if (arge < 2) 


kill8svx("No file name given.\n"); 
exit (1L); 


fname=argv [1]; 


feosee esos Sales Stele eee */ 
/* Initialize Clock Constant */ 
[euro a sss oa sees a ee */ 


GfxBase=(struct GfxBase *)OpenLibrary ("graphics. library", OL); 
if (GfxBase==0L) 
{ 


puts("Can’t open graphics library\n"); 
exit (1L); 
} 


if (GfxBase->DisplayFlags & PAL) 
clock=3546895L; /* PAL clock */ 
else 
clock=3579545L; /* NTSC clock */ 
if (GfxBase) 
CloseLibrary( (struct Library *) GfxBase); 


ft ea a ot */ 
/* Open the File * 
/* Soe elo oe eS Se */ 


v8handle= (struct FileHandle *) Open(fname,MODE_OLDFILE) ; 
if (v8handle==0) 


{ 

kill8svx("Can’t open 8SVX file.\n"); 
exit (1L); 

} 


Audio Device 29 


Koes ose oe Bee eee eo a ee ee Se x/ 
/* Read the lst 8 Bytes of the File for Size */ 
| haletatatetatatatetatetenmniniearmaaainintmaranssanatatatetetntatatetatanmaraa */ 


rd8count=Read ( (BPTR) v8handle, iobuffer, 8L) ; 
if (rd8count==-1) 


kill8svx ("Read error.\n"); 
exit (1L); 
} 

if (rd8count <8) 


{ 
kill8svx ("Not an IFF 8SVX file, too short\n"); 
exit (1L); 


[eeecsesl sc se lens */ 
/* Evaluate Header */ 
[¥en nnn nnn nnn nnn nnn */ 


p8Chunk=(Chunk *) iobuffer; 
if (p8Chunk->ckID != FORM ) 


{ 
kill8svx ("Not an IFF FORM. \n"); 
exit (1L); 


J Boson eee cS Sas ss ease esos a see ens cos Stes se */ 
i Allocate Memory for File and Read it in. */ 
BoP use seca ete */ 


ee (UBYTE *)AllocMem(fsize=p8Chunk->ckSize , MEMF_PUBLIC|MEMF_ CLEAR) ; 
if (fbase==0) 


kil18svx("No memory for read.\n"); 
exit (1L); 
} 


p8data=fbase; 


rd8count=Read ( (BPTR) v8handle, p8data, p8Chunk->ckSize) ; 
if (rd8count==-1) 

{ 

kill8svx ("Read error.\n"); 

exit (1L); 

} 


if (rd8count <p8Chunk->ckSize) 
{ 


kill8svx ("Malformed IFF, too short.\n"); 


exit (1L); 
} 

feosecetee iol ere */ 

/* Evaluate IFF Type */ 

[ewes sn-H3-555-5--5-= */ 

if (MakeID( *p8data, *(p8data+1l) , *(p8datat+2) , *(p8datat+3) ) != MY8S ) 
{ 
kill8svx ("Not an IFF 8SVX file.\n"); 
exit (1L); 
} 

peocseeen nits os obese * 

/* Evaluate 8SVX Chunks */ 

/* Sgt ois tas nn imap ip ul she, hs Sis it * 


p8data=p8datat4; 

while( p8data < fbase+fsize ) 
{ 
p8Chunk= (Chunk *) p8data; 


switch (p8Chunk->ckID) 
{ 


eae VHDR: 
Beet eet Soe soo ee en he eee a sae ses */ 
3 Get a pointer to the 8SVX header for later use */ 
Mos eoo ad Sete ea ee Be eh ee eae */ 


Oye ecelicude Wo teceneater *) (p8data+8L) ; 
break; 


30 Amiga ROM Kernel Reference Manual: Devices 


case BODY: 
[RR aR AROS S Aan aaa ne esas tena ee saan eaE se ess— HH Ress */ 
/* Create pointers to 1-shot and continuous parts */ 
/* for the top octave and get length. Store them. */ 
[¥escmesvenes aeucssesc so Se Bebe Sse et Sas ee ees */ 
psample[0] (BYTE *) (p8data + 8L); 


psample[1] = psample[0] + pVoice8Header->oneShotHiSamples; 


length[0] = (ULONG) pVoice8Header->oneShotHiSamples; 
length[1] = (ULONG) pVoice8Header->repeatHiSamples; 
break; 
default: 
break; 


} 


/* end switch */ 
p8data = p8data + 8L + p8Chunk->ckSize; 


if (p8Chunk->ckSize&1L == 1) 
p8datat++; 
} 


/* Play either the one-shot or continuous, not both */ 
if (length[0]== 

y=1; 
else 

y=0; 


/* Allocate chip memory for samples and */ 
/* copy from read buffer to chip memory. 
Xam ewww wwn ween own now nnn nn nn 
if (length[y] <=102400) 
ssize=length[y]; 

else 
ssize=102400; 


sbase=(UBYTE *)AllocMem( ssize , MEMF_CHIP | MEMF_ CLEAR); 
if (sbase==0) 
{ 


kill8svx ("No chip memory.\n"); 
exit (1L); 
} 


CopyMem(psample[y],sbase, ssize) ; 
psample[y]+=ssize; 


[Reawsecessa asec lacs caches cS eseieh */ 

/* Calculate playback sampling rate */ 

[Ronan eces eel oi sect e asa eee ous */ 

speed = clock / pVoice8Header->samplesPerSec; 
feioens Hotes Po sose se */ 


fT cpindeask bids 
oldpri=SetTaskPri (mt,21); 


Jee tosteeSs sole BSS esSs See sess */ 
/* Allocate two audio I/O blocks */ 
bale ai ialeeccat ag aaa oi Rae CRE SEE a */ 


AIOptri=(struct IOAudio *) 


AllocMem( sizeof (struct IOAudio) ,MEMF_PUBLIC|MEMF_CLEAR) ; 


if (AIOptr1==0) 
{ 
kill8svx("No IO memory\n"); 
exit (1L); 
} 


AIOptr2=(struct IOAudio *) 


AllocMem( sizeof (struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR) ; 


if (AIOptr2==0) 


kill8svx("No IO memory\n") ; 
exit (1L); 
} 


Audio Device 31 


portl=CreatePort (0,0); 
if (portl==0) 


{ 

kill8svx("No port\n"); 
exit (1L); 

} 


port2=CreatePort (0,0); 
if (port2==0) 
{ 


kill8svx("No port\n"); 
exit (1L); 
} 


c=0; 
while (device!=0 && c<4) 


/* Set up audio I/O block for channel */ 
/* allocation and Open the audio device */ 


AlOptri->ioa Data 


chans([c); 


AlOptr1->ioa Request.io Message.mn_ReplyPort = portl; 
AlOptrl->ioa Request.io Message.mn_Node.ln Pri = 127; /* No stealing! */ 
AlIOptrl1->ioa “AllocKey = 0; 


AlOptrl->ioa_ Length 
device=OpenDevice (AUDIONAME, OL, (struct IORequest *) 
ctt; 

} 


if (device!=0) 


kill8svx("No channel\n"); 
exit (1L); 
} 


AlOptrl->ioa_ Request.io Command =CMD WRITE; 
AlOptrl->ioa_ Request.io Flags =ADIOF_PERVOL; 


AlIOptr1->ioa_Period =(UWORD) speed; 
AlOptrl->ioa Cycles =1; 


*ATOptr2 = *AIOptrl; /* Make sure we have the same 
/* same channels selected and 


, 


AlOptr1, 0L); 


allocation keys, */ 
same flags 


/* (but different ports...) */ 
AlOptr1->ioa_Request.io Message.mn_ReplyPort = portl; 
AlOptr2->ioa_ Request.io Message.mn_ReplyPort = port2; 
[Reessees2 */ 
/* Data */ 
/* a a as es ee * 
AlOptr1->ioa Data =(UBYTE *) sbase; 
AlOptr2->ioa_ Data =(UBYTE *)sbase + 51200; 


32 Amiga ROM Kernel Reference Manual: Devices 


feiesices sacs fsee */ 
/* Run the sample * 
/* wmweeew new eee eww eee * 


if (length[y] <=102400) 


{ 

AlIOptrl->ioa_Length=length[y]; /* No double buffering needed */ 
BeginIO((struct IORequest *)AIOptr1); /* Begin the sample, wait for */ 
wakebit=0L; /* it to finish, then quit. */ 


wakebit=Wait (1 << portl->mp_SigBit); 
while ((msg=GetMsg (port1) )==0) {}; 
} 


else 


{ 

length [y] -=102400; /* It’s a real long sample so */ 
AlIOptr1->ioa_Length=51200L; /* double buffering is needed */ 
AlIOptr2->ioa_Length=51200L; 

BeginIO((struct IORequest *)AIOptr1); /* Start up the first 2 blocks... */ 
BeginIO((struct IORequest *)AIOptr2); 

Aptr=Al0Optr1; 

port=portl; /* Set the switch... */ 


while (length[y] >0) 
{ /* We Wait() for one IO to finish, */ 
wakebit=Wait(1 << port->mp_SigBit); /* then reuse the IO block & queue */ 
while ( (msg=GetMsg (port) ) ==0) {}; /* it up again while the 2nd IO */ 
/* block plays. Switch and repeat. */ 
/* Set length of next IO block */ 
if (length[y] <=51200) 
Aptr->ioa_Length=length[y]; 
else 
Aptr->ioa_Length=51200L; 


/* Copy sample fragment from read buffer to chip memory */ 
CopyMem(psample[y],Aptr->ioa_Data,Aptr->ioa_Length); 


/* Adjust size and pointer of read buffer*/ 
length [y] -=Aptr->ioa_Length; 
psample [y] +=51200; 

BeginIO((struct IORequest *)Aptr); 


if (Aptr==AIOptr1) 
{ 


Aptr=AlOptr2; /* This logic handles switching */ 

port=port2; /* between the 2 IO blocks and */ 

} /* the 2 ports we are using. */ 
else 


{ 
Aptr=AlIOptrl1; 
port=portl; 

} 


/* OK we are at the end of the sample so just wait */ 
/* for the last two parts of the sample to finish */ 


wakebit=Wait (1 << port->mp_SigBit); 
while ( (msg=GetMsg (port) ) ==0) {}; 
if (Aptr==AIOptr1) 


{ 

Aptr=AlOptr2; /* This logic handles switching */ 

port=port2; /* between the 2 IO blocks and / 

} /* the 2 ports we are using. */ 
else 


{ 
Aptr=AlOptrl; 
port=portl; 


} 
wakebit=Wait (1 << port->mp_SigBit); 
while ( (msg=GetMsg (port) ) ==0) {}; 
} 


kil18(); 
exit (OL); 
} 


Audio Device 33 


/* a */ 
/* Abort the Read */ 
/* nie aa eee oe ae */ 
void 


kill8svx (kill8svxstring) 
char *kill8svxstring; 


{ 
puts (kill8svxstring) ; 


kil18(); 

} 

feeeddus de ceco Soe s elas sues */ 
/* Return system resources */ 
[eee mee ee les See ks aee */ 
void 

ki118() 


{ 
if (device ==0) 

CloseDevice((struct IORequest *)AIOptr1); 
if (portl !=0) 

DeletePort (portl); 
if (port2 !=0) 

DeletePort (port2); 
if (AIOptr1!=0) 

FreeMem( AlOptrl1,sizeof(struct IOAudio) ); 
if (AIOptr2!=0) 

FreeMem( AlOptr2,sizeof (struct IOAudio) ); 


if (mt!=0) 
SetTaskPri (mt, oldpri); 


if (sbase !=0) 

FreeMem (sbase, ssize); 
if (fbase !=0) 

FreeMem(fbase, fsize); 
if (v8handle!=0) 

Close ((BPTR) v8handle) ; 
} 


Additional Information on the Audio Device 


Additional programming information on the audio device can be found in the include files and the 
Autodocs for the audio device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. Information can also be found in the Amiga Hardware Reference Manual. 


Audio Device Information 


INCLUDES devices/audio.h 


devices/audio.i 


AUTODOCS audio.doc 





34 Amiga ROM Kernel Reference Manual: Devices 


chapter three 
CLIPBOARD DEVICE 


The clipboard device allows the exchange of data dynamically between one application and another. 
It is responsible for caching data that has been “cut” and providing data to “paste” in an application. 
A special “post” mode allows an application to inform the clipboard device that the application has 
data available. The clipboard device will request this data only if the data is actually needed. The 
clipboard will cache the data in RAM and will automatically spool the data to disk if necessary. 


The clipboard device is implemented as an Exec-style device, and supports random access reads 
and writes on data within the clipboard. All data in the clipboard must be in IFF format. A new 
library, iffparse.library, has been added to the Amiga libraries. The routines in iffparse.library can 
and should be used for reading and writing data to the clipboard. This chapter contains a brief 
discussion of IFF as it relates to the clipboard (for more details see Appendix A). 


New Clipboard Features for Version 2.0 


Feature Description 


CBD_CHANGEHOOK Device Command 









Compatibility Warning: The new features for the 2.0 clipboard device are not backwards 
compatible. 


Clipboard Device 35 


Clipboard Device Commands and Functions 


Command Command Operation 


CBD_CHANGEHOOK Specify a hook to be called when the data on the clipboard has 
changed (V36). 

CBD_CURRENTREADID _ Retum the Clip ID of the current clip to read. This is used to 
determine if a clip posting is still the latest cut. 

CBD_CURRENTWRITEID Retum the Clip ID of the latest clip written. This is used to 
determine if the clip posting data is obsolete. 


CBD_POST Post the availability of clip data. 

CMD_READ Read data from the clipboard for a paste. Data can be read from 
anywhere in the clipboard by specifying an offset >0 in the I/O 
request. 

CMD_UPDATE Indicate that the data provided with a write command is complete 
and available for subsequent read/pastes. 

CMD_WRITE Write data to the clipboard as a cut. 


Exec Functions as Used in This Chapter 


CloseDevice() Relinquish use of the clipboard device. All requests must be 
complete before closing. 

DoIOQ Initiate a command and wait for completion (synchronous request). 

GetMsg() Get next message from a message port. 

OpenDevice() Obtain use of the clipboard device. 

SendIOQ Initiate a command and retum immediately (asynchronous 
request). 


Exec Support Functions as Used in This Chapter 


CreateExtIO() Create an I/O request structure of type IOClipReq. This structure 
will be used to communicate commands to the clipboard device. 
CreatePort() Create a signal message port for reply messages from the clipboard 
device. Exec will signal a task when a message arrives at the port. 
DeleteExtIO() Delete an I/O request structure created by CreateExtIO(Q). 
DeletePort() Delete the message port created by CreatePort(). 


36 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The clipboard device operates like the other Amiga devices. To use it, you must first open the 
clipboard device, then send I/O requests to it, and then close it when finished. See the “Introduction 
to Amiga System Devices” chapter for general information on device usage. 


struct IOClipReq 
{ 


struct 
struct 
struct 
UWORD 
UBYTE 
BYTE 
ULONG 
ULONG 
STRPTR 
ULONG 
LONG 
‘e 


Message io Message; 
Device *io Device; 
Unit *io Unit; 
io_Command; 

io Flags; 

io Error; 
io_Actual; 
io_Length; 

io Data; 

io_Offset; 

io _ClipID; 


device node pointer */ 

unit (driver private) */ 

device command */ 

including QUICK and SATISFY */ 
error or warning num */ 

number of bytes transferred */ 
number of bytes requested */ 
either clip stream or post port */ 
offset in clip stream */ 

ordinal clip identifier */ 


See the include file devices/clipboard.h for the complete structure definition. 


The clipboard device I/O request, IOClipReq, looks like a standard I[ORequest structure except 
for the addition of the io_ClipID field, which is used by the device to identify clips. It must be set 
to zero by the application for a post or an initial write or read, but preserved for subsequent writes 
or reads, as the clipboard device uses this field internally for bookkeeping purposes. 


OPENING THE CLIPBOARD DEVICE 


Three primary steps are required to open the clipboard device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an extended I/O request structure of type IOClipReq using CreateExtIO(Q. 
e Open the clipboard device. Call OpenDevice(), passing the IOClipReq. 


struct MsgPort 


*ClipMP; 


struct IOClipReq *ClipI0; 


if (ClipMP=CreatePort (OL,OL) ) 


{ 
if (ClipIO=(struct IOClipReq *) 


/* pointer to message port*/ 
/* pointer to IORequest */ 


CreateExtIO(ClipMP, sizeof (struct IOClipReq) )) 


{ 
if (OpenDevice ("clipboard.device", 0L,ClipI0O, 0) ) 
printf ("clipboard.device did not open\n"); 


else 


{ 


else 


--- do device processing 


printf("Error: Could not create I0Request\n") ; 


else 


printf("Error: Could not create message port\n"); 


Clipboard Device 37 


CLIPBOARD DATA 


Data on the clipboard resides in one of three places. When an application posts a cut, the data resides 
in the private memory space of that application. When an application writes to the clipboard, either 
of its own volition or in response to a message from the clipboard requesting that it satisfy a post, 
the data is copied to the clipboard which is either memory or a special disk file. When the clipboard 
is not open, the data resides in the special disk file located in the directory specified by the CLIPS: 
logical AmigaDOS assign. 


Data on the clipboard is self-identifying. It must be a correct IFF (Interchange File Format) file; 
the rest of this section refers to IFF concepts. See the Appendix A in this manual for a complete 
description of IFF. If the top-level chunk is of type CAT with an identifier of CLIP, that indicates 
that the contained chunks are different representations of the same data, in decreasing order of 
preference on the part of the producer of the clip. Any other data is as defined elsewhere (probably 
a single representation of the cut data produced by an application). 


The iffparse.library also contains functions which simplify reading and writing of IFF data to the 
clipboard device. See the “IFF Parse Library” chapter of the Amiga ROM Kernel Reference Manual: 
Libraries for more information. 


A clipboard tool, which is an application that allows a Workbench user to view a clip, should 
understand the text (FTXT) and graphics (ILBM) form types. Applications using the clipboard 
to export data should include at least one of these types in a CAT CLIP so that their data can be 
represented on the clipboard in some form for user feedback. 


You should not, in any way, rely on the specifics of how files in CLIPS: are handled or named. The 
only proper way to read or write clipboard data is via the clipboard device. 


Play Nice! Keep in mind that while your task is reading from or writing to a clipboard 
unit, other tasks cannot. Therefore, it is important to be fast. If possible, make a copy of 
the clipboard data in RAM instead of processing it while the read or write is in progress. 


MULTIPLE CLIPS 


The clipboard supports multiple clips, i.e., the clipboard device can contain more than one distinct 
piece of data. This is not to be confused with the IFF CAT CLIP, which allows for different 
representation of the same data. 

The multiple clips are implemented as different units in the clipboard device. The unit is specified 
at OpenDevice() time. 

struct IOClipReq *ClipI0O; 

LONG unit; 


OpenDevice ("clipboard.device", unit, ClipIO, 0); 


By default, applications should use clipboard unit 0. However, it is recommended that each 
application provide a mechanism for selecting the unit number which will be used when the 
clipboard is opened. This will allow the user to create a convention for storing different types of 
data in the clipboard. Applications should never write to clipboard unit 0 unless the user requests 
it (e.g., selecting COPY or CUT within an application). 


38 Amiga ROM Kernel Reference Manual: Devices 


Clipboard units 1-255 can be used by the more advanced user for: 
e Sharing data between applications within an ARexx Script. 
e Customizing applications to store different kinds of data in different clipboard units. 
e Customizing an application to use multiple cut/copy/paste buffers. 


Specialized utilities which might display and/or automatically modify the contents of a clipboard 
unit. 


All applications which provide CUT, COPY and PASTE capabilities, should, at a minimum, provide 
support for clipboard unit 0. 


WRITING TO THE CLIPBOARD DEVICE 


You write to the clipboard device by passing an IOClipReq to the device with CMD_WRITE set 
in io_Command, the number of bytes to be written set in io_Length and the address of the write 
buffer set in io_Data. 

ClipIO->io Data = (char *) data; 


ClipIO->io Length = 4L; 
ClipI0O->io_Command = CMD_WRITE; 


An initial write should set io_Offset to zero. Each time a write is done, the device will increment 
io_Offset by the length of the write. 


As previously stated, the data you write to the clipboard must be in IFF format. This requires a 
certain amount of preparation prior to actually writing the data if it is not already in IFF format. A 
brief explanation of the IFF format will be helpful in this regard. 


For our purposes, we will limit our discussion to a simple formatted text (FTXT) IFF file. An FIXT 
file looks like: 






length of succeeding bytes 


CHRS 
length of succeeding bytes 


pad byte of zero if the preceding chunk has odd length 


Based on the above figure, a hex dump of an IFF FTXT file containing the string Enterprise would 
look like: 







0000 464F524D FORM 

0004 000000 16 (length of FTXT, CHRS, OxA and data) 
0008 46545854 FTXT 

000C 43485253 CHRS 

0010 0000000A (length of Enterprise) 

0014 456E7465 Ente 

0018 72707269 rpri 

001C 7365 se 


Clipboard Device 39 


A code fragment for doing this: 


LONG slen = strlen ("Enterprise") ; 
BOOL odd = (slen & 1); /* pad byte flag */ 


/* set length depending on whether string is odd or even length */ 
LONG length = (odd) ? slen + 1 : slen; 


/* Reset the clip id */ 
ClipIO->io_ClipID = 0; 
ClipI0O->io_ Offset = 0; 
error = writeLong ((LONG *) "FORM");/* "FORM" */ 


length += 12; /* add 12 bytes for FTXT, CHRS & length byte to string length */ 
error writeLong (&length); 


error = writeLong ((LONG *) "FTXT");/* "FTXT" for example */ 
error = writeLong ((LONG *) "CHRS");/* "CHRS" for example */ 
error = writeLong (&slen); /* # (length of string) */ 


ClipIO->io_Command = CMD_WRITE; 

ClipIO->io Data = (char *) string; 

ClipIO->io Length = slen; /* length of string */ 
error = (LONG) DoIO (clipIO); /* text string */ 


LONG writeLong (LONG * ldata) 

{ 
ClipIO->io_Command = CMD _WRITE; 
ClipIO->io Data = (char *) ldata; 
ClipIO->io Length = 4L; 
return ( (LONG) DoIO (clipIO) ); 


The fragment above does no error checking because it’s a fragment. You should always error check. 
See the example programs at the end of this chapter for the proper method of error checking. 


Iffparse That Data! Keep in mind that the functions in the iffparse.library can be used to 
write data to the clipboard. See the “IFF Parse Library” chapter of the Amiga ROM Kernel 
Reference Manual: Libraries for more information. 


UPDATING THE CLIPBOARD DEVICE 


When the final write is done, an update command must be sent to the device to indicate that the 
writing is complete and the data is available. You update the clipboard device by passing an 
IOClipReq to the device with CMD_UPDATE set in io_Command. 


ClipIO->io Command = CMD_UPDATE; 
DoIO(ClipIO); 


CLIPBOARD MESSAGES 


When an application performs a post, it must specify a message port for the clipboard to send a 
message to if it needs the application to satisfy the post with a write called the SatisfyMsg. 

struct SatisfyMsg 

{ 

struct Message sm Message; /* the length will be 6 */ 

UWORD = sm _ Unit; /* 0 for the primary clip unit */ 


LONG sm_ClipID; /* the clip identifier of the post */ 
} 


40 Amiga ROM Kernel Reference Manual: Devices 


This structure is defined in the include file devices/clipboard.h. 


If the application wishes to determine if a post it has recently performed is still the current clip, 
it should compare the io_ClipID found in the post request upon retum with that returned by the 
CBD_CURRENTREADID command. 


If an application has a pending post and wishes to determine if it should satisfy it (for exam- 
ple, before it exits), it should compare the io_ClipID of the post I/O request with that of the 
CBD_CURRENTWRITEID command. If the application receives a satisfy message from the clip- 
board device (format described below), it must immediately perform the write with the io_ClipID 
of the post. The satisfy message from the clipboard may be removed from the application message 
port by the clipboard device at any time (because it is re-used by the clipboard device). It is not 
dangerous to spuriously satisfy a post, however, because it is identified by the io_ClipID. 


The cut data is provided to the clipboard device via either a write or a post of the cut data. The 
write command accepts the data immediately and copies it onto the clipboard. The post command 
allows an application to inform the clipboard of a cut, but defers the write until the data is actually 
required for a paste. 


In the preceding discussion, references to the read and write commands of the clipboard device 
actually refer to a sequence of read or write commands, where the clip data is acquired and provided 
in pieces instead of all at once. 


The clipboard has an end-of-clip concept that is analogous to end-of-file for both read and write. 
The read end-of-file must be triggered by the user of the clipboard in order for the clipboard to 
move on to service another application’s requests, and consists of reading data past the end of file. 
The write end-of-file is indicated by use of the update command, which indicates to the clipboard 
that the previous write commands are completed. 


READING FROM THE CLIPBOARD DEVICE 


You read from the clipboard device by passing an IOClipReq to the device with CMD_READ set 
in io_Command, the number of bytes to be read set in io_Length and the address of the read buffer 
set in io_Data. 

ClipI0O->io Command = CMD_READ; 


ClipIO->io Data = (char *) read data; 
ClipI0O->io_ Length = 20L; 


io_Offset must be set to zero for the first read of a paste sequence. An io_Actual that is less than the 
io_Length indicates that all the data has been read. After all the data has been read, a subsequent 
read must be performed (one whose io_Actual returns zero) to indicate to the clipboard device that 
all the data has been read. This allows random access of the clip while reading. Providing only valid 
reads are performed, your program can seek/read anywhere within the clip by setting the io_Offset 
field of the I/O request appropriately. 


Tell The Clipboard You Are Finished Reading. Your application must perform an 
extra read (one whose io_Actual returns zero) to indicate to the clipboard device that all 
data has been read, if io_Actual is not already zero. 


The data you read from the clipboard will be in IFF format. Conversion from IFF may be necessary 
depending on your application. 


Clipboard Device 41 


Iffparse That Data! Keep in mind that the functions in the iffparse.library can be used 
to read data from the clipboard. See the “IFF Parse Library” chapter of the Amiga ROM 
Kernel Reference Manual: Libraries for more information. 


CLOSING THE CLIPBOARD DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). 


CloseDevice (ClipIO) ; 


When the last task closes a clipboard unit with CloseDevice(), the contents of the unit may be 
copied to a disk file in CLIPS: so that the clipboard device can be expunged. 


Monitoring Clipboard Changes 


Some applications require notification of changes to data on the clipboard. Typically, these appli- 
cations will need to do some processing when this occurs. You can set up such an environment 
through the CBD_CHANGEHOOK command. CBD_CHANGEHOOK allows you to specify a 
hook to be called when the data on the clipboard changes. 


For example, a show clipboard utility would need to know when the data on the clipboard is changed 
so that it can display the new data. The hook it would specify would read the new clipboard data 
and display it for the user. 


You specify a hook for the clipboard device by initializing a Hook structure and then passing an 
IOClipReq to the device with CBD_CHANGEHOOK set in io_Command, 1 set in io_Length, 
and the address of the Hook structure set in io_Data. 


ULONG HookEntry (); /* Declare the hook assembly function */ 

struct IOClipReq *ClipI0O; /* Declare the IOClipReq */ 

struct Hook *ClipHook; /* Declare the Hook */ 

/* Prepare the hook */ 

ClipHook~>h_Entry = HookEntry; /* C interface in assembly routine HookEntry */ 
ClipHook->h_SubEntry = HookFunc; /* Function to call when Hook is activated */ 
ClipHook->h_Data = FindTask (NULL); /* Set pointer to current task */ 

ClipIO->io Data = (char *) ClipHook; /* Point to hook struct */ 

ClipI0O->io Length = 1; /* Add hook to clipboard */ 


ClipIO->io Command = CBD_CHANGEHOOK; 
DoIO(clipI0O); 


The above code fragment assumes that an assembly language routine HookEntry() has been coded: 


7 entry interface for C code 


_HookEntry: 
move.l al,-(sp) ; push message packet pointer 
move.l a2,-(sp) 7 push object pointer 
move.l a0,-(sp) ¢ push hook pointer 
move.l1 h_SubEntry(a0),a0 ; fetch C entry point ... 
jsxr (a0) yp o.e. and call it 
lea 12(sp),sp 3 fix stack 
rts 


42 Amiga ROM Kernel Reference Manual: Devices 


It also assumes that the function HookFunc() has been coded. One of the example programs at the 
end of this chapter has hook processing in it. See the include file utility/hooks.h and The Amiga 
ROM Kernel Reference Manual: Libraries for further information on hooks. 


You remove a hook by passing an IOClipReq to the device with the address of the Hook structure 
set in io_Data, 0 set in io_Length and CBD_CHANGEHOOK set in io_Command. 

ClipIO->io_ Data = (char *) ClipHook; /* point to hook struct */ 

ClipIO->io_ Length = 0; /* Remove hook from clipboard */ 


ClipIO->io_Command = CBD_CHANGEHOOK; 
(DoIO (clipIo) ) 


You must remove the hook or it will continue indefinitely. 


CAVEATS FOR CBD_CHANGEHOOK 


e CBD_CHANGEHOOK should only be used by a special application, such as a clipboard 
viewing program. Most applications can check the contents of the clipboard when, and if, the 
user requests a paste. 


e Do not add system overhead by blindly reading and parsing the clipboard everytime a user 
copies data to it. If all applications did this, the system could become intolerably slow whenever 
an application wrote to the clipboard. Only read and parse when it is necessary. 


Example Clipboard Programs 


/* 

* Clipdemo.c 

* 

* Demonstrate use of clipboard I/O. Uses general functions 
* provided in cbhio.c 

* 

* Compile with SAS C 5.10: LC -bl -cfistq -v -y -Ltcbio.o 

* 

* Run from CLI only 

*/ 


#include <exec/types.h> 

#include <exec/ports.h> 

#include <exec/io.h> 

#include <exec/memory.h> 
#include <devices/clipboard.h> 
#include <libraries/dosextens.h> 
#include <libraries/dos.h> 


#include "cb.h" 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#endif 


#define FORGETIT 0 


#define READIT 1 
#define WRITEIT 2 


Clipboard Device 43 


#define POSTIT 3 


/* prototypes */ 


int ReadClip( void ); /* Demonstrate reading clipboard data */ 
int WriteClip( char * ); /* Demonstrate write to clipboard */ 
int PostClip( char * ); /* Demonstrate posting data to clipboard */ 


void main( USHORT, char **); 


char message[] = "\ 

\nPossible switches are:\n\n\ 

-r Read, and output contents of clipboard.\n\ 

-w [string] Write string to clipboard.\n\n\ 

-p [string] Write string to clipboard using the clipboard POST mechanism. \n\n\ 
The Post can be satisfied by reading data from\n\ 
the clipboard. Note that the message may never\n\ 
be received if some other application posts, or\n\ 
performs an immediate write to the clipboard.\n\n\ 
To run this test you must run two copies of this example.\n\ 
Use the -p switch with one to post data, and the -r switch\n\ 
with another to read the data.\n\n\ 
The process can be stopped by using the BREAK command, \n\ 
in which case this example checks the CLIP write ID\n\ 
to determine if it should write to the clipboard before\n\ 
exiting.\n\n"; 


void main(argc, argv) 
USHORT argc; 
char **argv; 


{ 


int todo; 
char *string; 


todo = FORGETIT; 
if (argc) /* from CLI ? */ 
{ 
/* Very simple code to parse for arguments - will suffice for 
* the sake of this example 
*/ 
if (arge > 1) 
{ 
if (!(stremp(argv[1],"-r"))) 
todo = READIT; 
if (!(stremp(argv[1],"-w"))) 
todo = WRITEIT; 
if (!(stremp(argv[1],"-p"))) 
todo = POSTIT; 
string = NULL; 


if (arge > 2) 
string=argv [2]; 


} 


switch (todo) 
{ 


case READIT: 


ReadClip(); 
break; 


case POSTIT: 


PostClip (string); 
break; 


case WRITEIT: 


WriteClip(string); 


44 Amiga ROM Kernel Reference Manual: Devices 


break; 
default: 


ee eae 
reak; 


} 


/* 
* Read, and output FTXT in the clipboard. 
* 


x/ 
ReadClip() 
{ 
struct IOClipReq *ior; 
struct cbbuf *buf; 
/* Open clipboard.device unit 0 */ 


if (ior=CBOpen (0L) ) 
{ 


/* Look for FTXT in clipboard */ 


if (CBQueryFTXT (ior) ) 
{ 


/* Obtain a copy of the contents of each CHRS chunk */ 
while (buf=CBReadCHRS (ior) ) 
/* Process data */ 
printf ("ts\n", buf->mem) ; 
/* Free buffer allocated by CBReadCHRS() */ 
fee oer 
/* The next call is not really needed if you are sure */ 
/* you read to the end of the clip. */ 
CBReadDone (ior); 
sue 
Aiea FTXT in clipboard"); 
CBClose (ior); 
} 
else 


puts("Error opening clipboard unit 0"); 


} 
return (OL); 


/* 
* Write a string to the clipboard 
x 


«if 


WriteClip (string) 
char *string; 


{ 


Clipboard Device 45 


struct I0ClipReq *ior; 
if (string == NULL) 
{ 


puts("No string argument given"); 
return (OL); 


/* Open clipboard.device unit 0 */ 
if (ior = CBOpen (OL) ) 
if (! (CBWriteFTXT (ior, string) )) 
printf("Error writing to clipboard: io Error = %ld\n",ior->io_Error); 
caclose (Ler); 


else 
{ 
puts ("Error opening clipboard.device") ; 


} 


return (0); 


Write a string to the clipboard using the POST mechanism 


The POST mechanism can be used by applications which want to 
defer writing text to the clipboard until another application 
needs it (by attempting to read it via CMD_READ). However 

note that you still need to keep a copy of the data until you 
receive a SatisfyMsg from the clipboard.device, or your program 
exits. 


In most cases it is easier to write the data immediately. 


If your program receives the SatisfyMsg from the clipboard.device, 
you MUST write some data. This is also how you reply to the message. 


If your program wants to exit before it has received the SatisfyMsg, 
you must check the io ClipID field at the time of the post against 

the current post ID which is obtained by sending the CBD_CURRENTWRITEID 
command. 


If the value in io ClipID (returned by CBD_CURRENTWRITEID) is greater 
than your post ID, it means that some other application has performed 

a post, or immediate write after your post, and that you’re application 
will never receive the SatisfyMsg. 


If the value in io ClipID (returned by CBD_CURRENTWRITEID) is equal 
to your post ID, then you must write your data, and send CMD_UPDATE 
before exiting. 


4 % Oe Oe Oe 


SS 


PostClip(string) 
char *string; 


{ 


struct MsgPort *satisfy; 
struct SatisfyMsg *sm; 
struct IOClipReq *ior; 
int mustwrite; 

ULONG postID; 


if (string == NULL) 
{ 
puts("No string argument given"); 
return (OL); 


} 


if (satisfy = CreatePort (OL, 0L)) 
{ 


46 Amiga ROM Kernel Reference Manual: Devices 


/* Open clipboard.device unit 0 */ 
if (ior = CBOpen(0L)) 
ere = FALSE; 
/* Notify clipboard we have data */ 


ior->io Data (STRPTR) satisfy; 


ior->io ClipID OL; 
ior->io_ Command = CBD_POST; 
DoIO( (struct IORequest *) ior); 


postID = ior->io ClipID; 


printf ("\nClipID = %ld\n", postID); 


/* Wait for CTRL-C break, or message from clipboard */ 


Wait (SIGBREAKF_ CTRL C| (1L << satisfy->mp_SigBit)); 

/* see if we got a message, or a break */ 

puts ("Woke up"); 

if (sm = (struct SatisfyMsg *)GetMsg(satisfy) ) 
puts("Got a message from the clipboard\n"); 


/* We got a message - we MUST write some data */ 
mustwrite = TRUE; 
} 


else 
/* Determine if we must write before exiting by 
* checking to see if our POST is still valid 
* 
ior->io_ Command = CBD _CURRENTWRITEID; 
DoIO( (struct IORequest *) ior); 
printf ("CURRENTWRITEID = %ld\n",ior->io_ClipID); 


if (postID >= ior->io_ClipID) 
mustwrite = TRUE; 


} 
/* Write the string of text */ 
if (mustwrite) 


if (! (CBWriteFTXT (ior, string) )) 
puts ("Error writing to clipboard"); 
} 


else 


puts("No need to write to clipboard"); 


CBClose (ior); 
} 


else 


puts("Error opening clipboard.device"); 


DeletePort (satisfy); 
} 


else 


puts("Error creating message port"); 


return(0); 


} 


Clipboard Device 47 


/* 
* Changehook Test.c 

* 

* Demonstrate the use of CBD _CHANGEHOOK command. 

* The program will set a hook and wait for the clipboard data to change. 
* You must put something in the clipboard in order for it to return. 

* 

* Compile with SAS C 5.10: LC -cfist -v -y -LtHookface.o+cbio.o 

* 

* Requires Kickstart 36 or greater. 

* 

* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/ports.h> 
#include <exec/tasks.h> 
#include <exec/io.h> 

#include <devices/clipboard.h> 
#include <dos/dos.h> 

#include <utility/hooks.h> 
#include "cb.h" 


#include <clib/macros.h> 

#include <clib/alib protos.h> 

#include <clib/exec_protos.h> 

#include <stdio.h> 

#include <string.h> 

LONG version = 1L; 

extern ULONG SysBase, DOSBase; 

/* Data to pass around with the clipHook */ 


struct CHData 
{ 


struct Task *ch_ Task; 
LONG ch_ClipID; 
he 
struct MsgPort *clip port; 
struct Hook hook; 
struct CHData ch; 
ULONG clipHook (struct Hook * h, VOID * o, struct ClipHookMsg * msg) 
{ 
struct CHData *ch = (struct CHData *) h->h_Data; 
if (ch) 


{ 
/* Remember the ID of clip */ 
ch->ch_ClipID = msg->chm_ClipID; 


/* Signal the task that started the hook */ 
signal (ch->ch_Task, SIGBREAKF CTRL E); 
return (0); 
} 
struct IOClipReq *OpenCB (LONG unit) 
seeize IOClipReq *clipI0; 
/* Open clipboard unit 0 */ 
if (clipIO = CBOpen( OL )) 
ere hookEntry (); 
/* Fill out the IORequest */ 


clipIO->io Data = (char *) &hook; 
clipI0O->io_ Length = 1; 


48 Amiga ROM Kernel Reference Manual: Devices 


clipIO->io_Command = CBD_CHANGEHOOK; 


/* Set up the hook data */ 
ch.ch_Task = FindTask (NULL); 


/* Prepare the hook */ 
hook.h_ Entry = hookEntry; 
hook.h_ SubEntry = clipHook; 
hook.h_ Data = &ch; 


/* Start the hook */ 
if (DoIO (clipI0) ) 
printf ("unable to set hook\n"); 
else 
printf ("hook set\n"); 
/* Return success */ 
return ( clipIO ); 
} 


/* return failure */ 
return (NULL); 
} 


void CloseCB (struct IOClipReq *clipIO) 
{ 


/* Fill out the IO request */ 
clipIO->io_Data = (char *) &hook; 
clipI0O->io_ Length = 0; 
clipI0O->io Command = CBD_CHANGEHOOK; 
/* Stop the hook */ 
if (DoIO (clipI0) ) 
printf ("unable to stop hook\n"); 
else 
/* Indicate success */ 
printf ("hook is stopped\n"); 


CBClose (clipIO) ; 
} 


main (int argc, char **argv) 
theate IOClipReq *clipI0O; 
ULONG sig_revd; 
printf ("Test v%ld\n", version); 
if (clipIO=OpenCB (OL) ) 
howe = Wait ((SIGBREAKF _CTRL_C | SIGBREAKF_CTRL E)); 


if (sig _rcvd & SIGBREAKF CTRL C) 
printf ("°C received\n"); 


if (sig_rcvd & SIGBREAKF_CTRL_E) 


printf ("clipboard change, current ID is %ld\n", ch.ch ClipID); 


CloseCB (clipI0O); 
} 


Clipboard Device 49 


Support Functions Called from Example Programs 


/* Chio.c 
* 
Provide standard clipboard device interface routines 
such as Open, Close, Post, Read, Write, etc. 


Compile with SAS C 5.10: LC -bl -cfistq -v -y 


* 
* 
* 
* 
* 
* NOTE - These functions are useful for writing, and reading simple 
* FTXT. Writing, and reading complex FTXT, ILBM, etc., 

* requires more work - under 2.0 it is highly recommended that 
x you use iffparse.library. 

* 


/ 


#include <exec/types.h> 
#include <exec/ports.h> 
#include <exec/io.h> 

#include <exec/memory.h> 
#include <devices/clipboard.h> 


#define CBIO 1 
#include "cb.h" 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 


77000000 C70 /CBOpen GGG IIIS II IG ICIS IIIS ICI TOI ITI TI IA IK 
* 


A pointer to an initialized IOClipReq structure, or 
a NULL pointer if the function fails. 


* NAME 

* CBOpen() -- Open the clipboard.device 

* 

* SYNOPSIS 

* ior = CBOpen (unit) 

* 

* struct I0ClipReq *CBOpen( ULONG ) 

* 

* FUNCTION 

* Opens the clipboard.device. A clipboard unit number 
* must be passed in as an argument. By default, the unit 
* number should be 0 (currently valid unit numbers are 
* 0-255). 

* 

* RESULTS 

x 

* 

x 

* 


FOI III OI III IOI III IO IO IO IOI IOI III IK IK II IK 


struct IOClipReq *CBOpen (unit) 
ULONG unit; 
teed MsgPort *mp; 
struct IOStdReq *ior; 
if (mp = CreatePort (OL, OL) ) 
te (ior=CreateExtIO(mp, sizeof (struct IOClipReq) )) 
if (! (OpenDevice ("clipboard.device",unit,ior,0OL))) 
return((struct IOClipReq *)ior); 
pene Sedhoiecig 
eter seovetndis 
eee Waits 


} 


50 Amiga ROM Kernel Reference Manual: Devices 


[RKKKK cbhio/CBClose WK KK IK KK KKK KK KK KKK KK KKK KKK KKK KK KEKE KKK KK KEKE KKK 


NAME 
CBClose() -- Close the clipboard.device 


SYNOPSIS 
CBClose () 


FUNCTION 
Close the clipboard.device unit which was opened via 


* 
* 

* 

* 

* 

* 

* 

* void CBClose() 
* 

* 

* 

* CBOpen(). 
* 

* 


FIO IOI IOI III OOOO IOI IAAI IOI] 


void CBClose (ior) 
struct IOClipReq *ior; 
{ 

struct MsgPort *mp; 


mp = ior->io_Message.mn_ReplyPort; 
CloseDevice((struct IOStdReq *)ior); 
DeleteExtIO((struct IOStdReq *)ior); 
DeletePort (mp) ; 

} 


*0OK%™) Chio/CBWILtePR TXT Og IIIS III IID IIIA IOOI III IOI 


NAME 


CBWriteFTXT() -- Write a string of text to the clipboard.device 


SYNOPSIS 
success = CBWriteFTXT( ior, string) 


int CBWriteFTXT(struct I0ClipReq *, char *) 


Write a NULL terminated string of text to the clipboard. 
The string will be written in simple FTXT format. 


Note that this function pads odd length strings automatically 
to conform to the IFF standard. 


/ 

* 

* 

* 

* 

* 

* 

* 

* 

* 

* FUNCTION 
* 

* 

* 

* 

* 

x 

* RESULTS 

* TRUE if the write succeeded, else FALSE. 
* 
* 


FOI III IOI III IO IOI IA III K 


int CBWriteFTXT (ior, string) 
struct IO0ClipReq *ior; 
char *string; 


{ 

ULONG length, slen; 
BOOL odd; 

int success; 


slen = strlen(string); 
odd = (slen & 1); /* pad byte flag */ 


length = (odd) ? slen+l : slen; 
/* initial set-up for Offset, Error, and ClipID */ 
lor->io_Offset 


ior->io_ Error 
lor->io_ClipID 


toneow 


0; 
0; 
0; 
/* Create the IFF header information */ 


WriteLong(ior, (long *) "FORM"); /* "FORM" x/ 
length+=12L; /* + “({size]FTXTCHRS" */ 


Clipboard Device 51 


WriteLong(ior, &length); /* total length */ 
WriteLong(ior, (long *) "FTXT"); /* "PTXT" */ 
WriteLong(ior, (long *) "CHRS"); /* “CHRS" x/ 
WriteLong(ior, &slen); /* string length */ 


/* Write string */ 

lor->io Data = (STRPTR) string; 
ior->io_Length = slen; 
ior->io_Command = CMD _WRITE; 
DoIO( (struct IORequest *) ior); 


/* Pad if needed */ 

if (odd) 
{ 
ior->io Data = (STRPTR)""; 
jior->io_Length = 1L; 
DoIO( (struct IORequest *) ior); 
} 


/* Tell the clipboard we are done writing */ 


ior->io_Command=CMD_UPDATE; 
DoIO( (struct IORequest *) ior); 


/* Check if io Error was set by any of the preceding IO requests */ 
success = ior->io_Error ? FALSE : TRUE; 


return (success) ; 


} 


WriteLong(ior, ldata) 
struct IOClipReq *ior; 
long *ldata; 

{ 


ior->io Data 
ior->io_Length 4L; 
ior->io_Command = CMD WRITE; 
DoIO( (struct IORequest *) ior); 


(STRPTR) ldata; 


if (ior->io Actual == 4) 
{ 
return( ior->io Error ? FALSE : TRUE); 
} 


return (FALSE) ; 


} 


[RKKKKK cbhio/CBQueryFTXT Fe IK KK I KKK KKK KKK KKK KKK KEKE KKK KKK KKK 
x 

* NAME 

* CBQueryFTXT() -- Check to see if clipboard contains FTXT 
* 

* SYNOPSIS 

* result = CBQueryFTXT( ior ) 

* 

* int CBQueryFTXT (struct IOClipReq *) 

* 

* FUNCTION 

- Check to see if the clipboard contains FTXT. If so, 

* call CBReadCHRS() one or more times until all CHRS 

* chunks have been read. 

* 

* RESULTS 

= TRUE if the clipboard contains an FTXT chunk, else FALSE. 
* 

* NOTES 

* If this function returns TRUE, you must either call 

* CBReadCHRS() until CBReadCHRS() returns FALSE, or 

* call CBReadDone() to tell the clipboard.device that 

* you are done reading. 

* 

* 

FIO III III IO III IOI IO III III III IO IO IO IO IOI OK I IK / 


52 Amiga ROM Kernel Reference Manual: Devices 


int CBQueryFTXT (ior) 
struct IOClipReq *ior; 


{ 
ULONG cbhuff [4]; 


/* initial set-up for Offset, Error, and ClipID */ 


ior->io_ Offset = 0; 
lor->io_ Error = 0; 
ior->io_ClipID = 0; 


/* Look for "FORM[size]FTXT" */ 


ior->io_Command = CMD_READ; 
ior->io_Data = (STRPTR) cbhuff; 
ior->io_Length = 12; 


DoIO( (struct IORequest *) ior); 


/* Check to see if we have at least 12 bytes */ 


if (ior->io_Actual == 12L) 
{ 
/* Check to see if it starts with "FORM" */ 
if (cbuff[0] == ID_FORM) 
{ 


/* Check to see if its "FTXT" */ 


if (cbuff[2] == ID_FTXT) 
return (TRUE) ; 


/* It’s not "FORM[size]FTXT", so tell clipboard we are done */ 
} 
CBReadDone (ior) ; 


return (FALSE) ; 
} 


700%) Chio/CBRead Cl RS 200 GI III IIIS IIIT 


* 

* NAME 

x CBReadCHRS() -- Reads the next CHRS chunk from clipboard 

x 

* SYNOPSIS 

* cbbuf = CBReadCHRS( ior ) 

x 

x struct cbbuf *CBReadCHRS(struct IOClipReq * ) 

* 

* FUNCTION 

* Reads and returns the text in the next CHRS chunk 

7 (if any) from the clipboard. 

* 

* Allocates memory to hold data in next CHRS chunk. 

x 

* RESULTS 

* Pointer to a cbbuf struct (see cb.h), or a NULL indicating 
* a failure (e.g., not enough memory, or no more CHRS chunks). 
* 

Z ***Important*** 

* 

* The caller must free the returned buffer when done with the 
* data by calling CBFreeBuf (). 

* 

* NOTES 

* This function strips NULL bytes, however, a full reader may 
* wish to perform more complete checking to verify that the 

- text conforms to the IFF standard (stripping data as required). 
* 

7 Under 2.0, the AllocVec() function could be used instead of 
7 AllocMem() in which case the cbbuf structure may not be 

x needed. 

* 

* 


FOI III III II II III III II IIIT II II IC 


Clipboard Device 53 


struct cbbuf *CBReadCHRS (ior) 
struct IOClipReq *ior; 


{ 

ULONG chunk, size; 

struct cbbuf *buf; 

int looking; 

/* Find next CHRS chunk */ 


looking = TRUE; 
buf = NULL; 


while (looking) 
{ 
looking = FALSE; 
if (ReadLong (ior, &chunk) ) 
{ 


/* Is CHRS chunk ? */ 
if (chunk == ID_CHRS) 


/* Get size of chunk, and copy data */ 
if (ReadLong (ior, &size) ) 


if (size) 
buf=FillCBData (ior, size); 
} 


} 


/* If not, skip to next chunk */ 
else 


if (ReadLong(ior, &size) ) 
looking = TRUE; 
if (size & 1) 
sizett+; /* if odd size, add pad byte */ 


ior->io_ Offset += size; 


} 


} 


if (buf == NULL) 
CBReadDone (ior); /* tell clipboard we are done */ 


return (buf); 


ReadLong(ior, ldata) 
struct IOClipReq *ior; 
ULONG *ldata; 

{ 


ior->io_Command = CMD_READ; 
ior->io Data = (STRPTR) ldata; 
ior->io_ Length = 4L; 


DoIO( (struct IORequest *) ior); 
if (ior->io_Actual == 4) 


{ 
return( ior->io_ Error ? FALSE : TRUE); 


return (FALSE) ; 
} 


54 Amiga ROM Kernel Reference Manual: Devices 


struct cbbuf *FillCBData (ior, size) 
struct I0ClipReq *ior; 

ULONG size; 

{ 

register UBYTE *to,*from; 

register ULONG x, count; 


ULONG length; 
struct cbbuf *buf, *success; 


success = NULL; 


if (buf = AllocMem(sizeof (struct cbbuf),MEMF PUBLIC) ) 
{ 


length = size; 
if (size & 1) 

lengtht+; /* if odd size, read 1 more */ 
if (buf->mem = AllocMem(lengtht1L,MEMF_PUBLIC) ) 

{ 


buf->size = length+1L; 


ior->io_Command = CMD_READ; 
ior->io Data = (STRPTR) buf->mem; 
ior->io_ Length = length; 


to = buf->mem; 
count = OL; 


if (!(DoIO( (struct IOStdReq *) ior))) 
if (ior->io_Actual == length) 
{ 
success = buf; /* everything succeeded */ 


/* strip NULL bytes */ 
for (x=0, from=buf->mem ;x<size;xt+t+) 


if (*from) 
{ 
*to = *from; 
Cort; 
count++; 


} 


fromt++; 


} 
*to=0x0; /* Null terminate buffer */ 


buf->count = count; /* cache count of chars in buf */ 


} 
} 


if (! (success) ) 
FreeMem(buf->mem, buf->size) ; 


if (! (success) ) 
FreeMem(buf, sizeof (struct cbbuf)); 
} 


return (success); 


} 


Clipboard Device 55 


[****k** chio/CBReadDone ORO IOI III III IO IOI III III ko 


NAME 
CBReadDone() -- Tell clipboard we are done reading 


SYNOPSIS 
CBReadDone( ior ) 


void CBReadDone(struct IOClipReq * ) 
FUNCTION 


* 
* 
* 
* 
* 
x 
* 
* 
* 
* 
* Reads past end of clipboard file until io Actual is equal to 0. 
* This is tells the clipboard that we are done reading. 

* 

FI III II II III III III III III IOI III IOI IOI III TIO I IOI II II III IK / 


void CBReadDone (ior) 
struct IOClipReq *ior; 
{ 


char buffer[256]; 


ior->io_ Command = CMD_READ; 

ior->io Data = (STRPTR) buffer; 

ior->io Length = 254; 

/* falls through immediately if io Actual == 0 */ 


while (ior->io Actual) 


{ 

if (DoIO( (struct IORequest *) ior)) 
break; 

} 


} 


/****** chio/CBFTeeBu f 1 II III III III GIIGIGIGISISI GIA SISI GIGI 


NAME 
CBFreeBuf() -- Free buffer allocated by CBReadCHRS () 


SYNOPSIS 
CBFreeBuf( buf ) 


void CBFreeBuf( struct cbhbuf * ) 


FUNCTION 
Frees a buffer allocated by CBReadCHRS(). 


* 
* 
* 
x 
* 
x 
* 
* 
* 
* 
* 
* 
* 


FO IIIS GIGI I IGIO IOI ISO III III III III III II ICI 7] 


void CBFreeBuf (buf) 

struct cbhbuf *buf; 

{ 

FreeMem(buf->mem, buf->size); 
FreeMem(buf, sizeof(struct cbbuf)); 


} 


56 Amiga ROM Kernel Reference Manual: Devices 


[eee eS 2S SSSSSSSSSALSSSLSSSLSSSLELSESELESS SSE SPSS SESS SSSESSSSSSS SSS SESS SSS SSS SSS 
Hookface.asm 


assembly routines for Chtest 


* 

* 

* 

* Assemble with Adapt hx68 hookface.a to hookface.o 

7 Link with Changehook_Test.o as shown in Changehook_ Test.c header 
* 
* 


FOI III SII OI ICICI II CIOICIOIOIICICICIOI OI DIGI COICO III GIGI ICICOOI IIIS II ICO OK 
INCDIR ‘include:’ 
INCLUDE ‘exec/types.i’ 
INCLUDE ‘utility/hooks.i’ 


xdef _¢callHook 
xdef _callHookPkt 
xdef _hookEntry 
xdef stubReturn 


FOI IO IO IOI IOI IO IOI OO IO III II 


new hook standard 
use struct Hook (with minnode at the top) 


**x* register calling convention: *** 
AO - pointer to hook itself 
Al - pointer to parameter packed ("message") 
A2 - Hook specific address data ("object," e.g, gadget ) 


*x** C conventions: *** 

Note that parameters are in unusual register order: a0, a2, al. 
This is to provide a performance boost for assembly language 
programming (the object in a2 is most frequently untouched) . 

It is also no problem in "register direct" C function parameters. 


calling through a hook 
callHook( hook, object, msgid, pl, p2, ... ); 
callHookPkt( hook, object, msgpkt ); 


% eH HH HH HH HH OH HE OE OH OH OE 


using a C function: CFunction( hook, object, message ); 
hook.h_ Entry = hookEntry; 
* hook.h SubEntry = CFunction; 
FO IO III IO IO OI II III OI III OI IOI III I III IOI II I I 


* C€ calling hook interface for prepared message packet 


_callHookPkt: 
movem.1 a2/a6,-(sp) 7 protect 
move.l 12(sp),a0 3 hook 
move.l 16(sp),a2 7 object 
move.l 20(sp),al 7 message 
fj panss= now have registers ready, invoke function 
pea.l hreturn (pc) 
move.l h_Entry(a0),-(sp) ; old rts-jump trick 
rts 
hreturn: 
movem.1 (sp)+,a2/a6 
rts 


* C calling hook interface for "varargs message packet" 


_callHook: 
movem.1 a2/a6,-(sp) 3 protect 
move.l 12(sp),a0 3 hook 
move.l 16(sp),a2 7 object 
lea.l 20(sp),al 7; message 
ih ae ae now have registers ready, invoke function 
pea.l hpreturn (pc) 
move.l h_Entry(a0),-(sp) ; old rts-jump trick 
rts 
hpreturn: 
movem.1 (sp)+,a2/a6 
rts 


* entry interface for C code (large-code, stack parameters) 
_hookEntry: 

move.l al,-(sp) 

move.l a2,-(sp) 

move.l a0,-(sp) 


move.l h_SubEntry(a0),a0 7 C entry point 
jsr (a0) 
lea 12(sp),sp 
_StubReturn: 
rts 


Clipboard Device 57 


Include File for the Example Programs 


[DOO II IIIISIIAISISIAISIO ICICI IIT AT AIT ATI I ISI ITI TIN 


* 


* cb.h -- Include file used by clipdemo.c, changehook_test.c and cbio.c 


* 


FOI III IOI IIIT IK IK | 


struct cbbuf { 


ULONG size; 

ULONG count; 

UBYTE *mem; 
}e 


#define 


#define 
#define 
#define 


#ifdef CBIO 
/* prototypes */ 


struct IOClipReq 
void 

int 

int 

struct cbbuf 
void 

void 


/* routines which are meant to be used internally by routines in cbio */ 


int 
int 
struct cbbuf 


#telse 
/* prototypes */ 


extern 
extern 
extern 
extern 
extern 
extern 
extern 


struct IOClipReq 
void 

int 

int 

struct cbbuf 
void 

void 


#endif 


MAKE_ID(a,b,c,d) 


/* size of memory allocation 


*/ 


/* number of characters after stripping */ 


/* pointer to memory containing data 


((a<<24L) 


*CBOpen 
CBClose 
CBWriteFTXT 
CBQueryFTXT 
*CBReadCHRS 
CBReadDone 
CBFreeBuf 


WriteLong 
ReadLong 
*FillCBData 


*CBOpen 
CBClose 
CBWriteFTXT 
CBQueryFTXT 
*CBReadCHRS 
CBReadDone 
CBF reeBuf 


| (b<<16L) 


ID_FORM MAKE _ID(‘F’,‘0',’R’,‘M’) 
ID_FTXT MAKE ID(‘F’,/T!,’X!’,’T’) 
ID_CHRS MAKE_ID(‘C’,’H’,’R’,’S‘) 


( ULONG 
(struct 
(struct 
(struct 
(struct 
(struct 
(struct 


(struct 
(struct 
(struct 


{ ULONG 
(struct 
(struct 
(struct 
(struct 
(struct 
(struct 


oy, 


| (c<<8L) | d@) 


); 

IOClipReq 
I0ClipReq 
IOClipReq 
IOClipReq 
I0ClipReq 
cbbuf *); 


IOClipReq *, long *); 
IOClipReq *, ULONG *); 
IOClipReq *, ULONG); 


; 

IOClipReq *); 
IOClipReq *, char *); 
IOClipReq *) 
I0ClipReq 
IOClipReq 
cbbuf *); 


*); 
*); 


58 Amiga ROM Kernel Reference Manual: Devices 


Additional Information on the Clipboard Device 


Additional programming information on the clipboard device can be found in the include files for 
the clipboard device, iffparse library and utility library, and the Autodocs for all three. They are 
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs. 


Clipboard Device Information 


INCLUDES devices/clipboard.h 
devices/clipboard.i 
libraries/iffparse.h 
libraries/iffparse.h 


utility/hooks.h 
utility/hooks.i 


AUTODOCS clipboard.doc 
iffparse.doc 
utility.doc 





Clipboard Device 59 


chapter four 
CONSOLE DEVICE 


The console device provides the text-oriented interface for Intuition windows. It acts like an 
enhanced ASCII terminal obeying many of the standard ANSI sequences as well as special sequences 
unique to the Amiga. The console device also provides a copy-and-paste facility and an internal 
character map to redraw a window when it is resized. 


New Console Features for Version 2.0 


Description 


CONU_LIBRARY New #define 
CONU_STANDARD New #define 


CONU_CHARMAP Console Unit 
CONU_SNIPMAP Console Unit 
CONFLAG_DEFAULT Console Flag 
CONFLAG_NODRAW_ON_NEWSIZE Console Flag 





Compatibility Warning: The new features for the 2.0 console device are not backwards 
compatible. 


Console Device 61 


Console Device Commands and Functions 


Command 


Operation 


CD_ASKDEFAULTKEYMAP Get the current default keymap. 


CD_ASKKEYMAP 


Get the current key map structure for this console. 


CD_SETDEFAULTKEYMAP _ Set the current default keymap. 


CD_SETKEYMAP 
CMD_CLEAR 


CMD_READ 


CMD_WRITE 


Set the current key map structure for this console. 

Remove any reports waiting to satisfy read requests from the 
console input buffer. 

Read the next input, generally from the keyboard. The form of 
this input is as an ANSI byte stream. 

Write a text record to the display interpreting any ANSI control 
characters in the record. 


Console Device Function 


CDInputHandler() 
RawKeyConvert() 


Handle an input event for the console device. 
Decode raw input classes and convert input events of type 
IECLASS_RAWKEY to ANSI bytes based on the keymap in use. 


Exec Functions as Used in This Chapter 


AbortIO() 
CheckIOQ 
CloseDevice() 


DoIOQ 
GetMsg() 
OpenDevice() 


OpenLibrary() 
OpenWindow() 
SendIOQ 
Wait() 
WaitIO( 
WaitPort() 


Abort an I/O request to the console device. 

Retum the status of an I/O request. 

Relinquish use of the console device. All requests must be complete 
before closing. 

Initiate a command and wait for completion (synchronous request). 
Get the next message from the reply port. 

Obtain use of the console device. You specify the type of unit and its 
characteristics in the call to OpenDevice(). 

Gain access to a library. 

Open an intuition window. 

Initiate a command and return immediately (asynchronous request). 
Wait for one or more signals. 

Wait for completion of an I/O request and remove it from the reply port. 
Wait for the reply port to be non-empty. Does not remove the message 
from port. 


Exec Support Functions as Used in This Chapter 


CreateExtIO 
CreatePort() 


DeleteExtIO() 
DeletePort() 


Create an extended I/O request structure for use in communicating with 
the console device. 

Create a message port for reply messages from the console device. Exec 
will signal a task when a message arrives at the port. 

Delete the extended I/O request structure created by CreateExtIO(. 
Delete the message port created by CreatePort(). 


62 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The console device operates like the other Amiga devices. To use it, you must first open the console 
device, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
System Devices” chapter for general information on device usage. 


The I/O request used by the console device is called IOStdReq. 


struct I0StdReq 
{ 


struct Message io Message; 


struct Device *io Device; /* device node pointer */ 

struct Unit *io Unit; /* unit (driver private) */ 

UWORD io_Command; /* device command 

UBYTE io_ Flags; 

BYTE io Error; /* error or warning num */ 

ULONG io_Actual; /* actual number of bytes transferred */ 
ULONG io_Length; /* requested number bytes transferred*/ 
APTR io_Data; /* points to data area */ 

ULONG io Offset; /* offset for block structured devices */ 


he 


See the include file exec/io.h for the complete structure definition. 


CONSOLE DEVICE UNITS 


The console device provides four units, three that require a console window and one that does not. 
The unit type is specified when you open the device. See the “Opening the Console Device” section 
below for more details. 


The CONU_STANDARD unit (0) is generally used with a SMART_REFRESH window. This unit 


has the least amount of overhead (e.g., memory usage and rendering time), and is highly compatible 
with all versions of the operating system. 


As of V36, a character mapped console device was introduced. There are two variations of character 
mapped console units. Both must be used with SIMPLE_REFRESH windows and both have the 
ability to automatically redraw a console window when resized or revealed. 


A character mapped console can be opened which allows the user to drag-select text with the mouse 
and COPY the highlighted area. The copied text can then be PASTEd into other console windows 
or other windows which support reading data from the clipboard device. 


Character mapped console units have more overhead than standard consoles (e.g., rendering times 
and memory usage). 


The CONU_LIBRARY unit (-1) does not require a console window. It is designed to be primarily 
used with the console device functions and also with the console device commands that do not 
require a console window. 


The Amiga uses the ECMA-94 Latin1 International 8-bit character set. See Appendix A (page 397) 
for a table of character codes. 


Console Device 63 


OPENING THE CONSOLE DEVICE 


Four primary steps are required to open the console device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an I/O request structure of type IOStdReq. The [OStdReq structure is created by the 
CreateExtIO() function. CreateExtIO will initialize your I/O request to point to your reply 
port. 


e Open an Intuition window and set a pointer to it in the io_Data field of the IOStdReq and the 
size of the window in the io_Length field. This is the window to which the console will be 
attached. The window must be SIMPLE_REFRESH for use with the CONU_CHARMAP and 
CONU_SNIPMAP units. 


e Open the console device. Call OpenDevice() passing it the I/O request and the type of console 
unit set in the unit and flags fields. Console unit types and flag values are listed below. 


Console device units: 


e CONU_LIBRARY - Retum the device library vector pointer used for calling console device 
functions. No console is opened. 


e CONU_STANDARD - Open a standard console. 
e CONU_CHARMAP - Open a console with a character map. 
e CONU_SNIPMAP - Open a console with a character map and copy-and-paste support. 


See the include file devices/conunit.h for the unit definitions and the Amiga ROM Kernel Reference 
Manual: Includes and Autodocs for an explanation of each unit. 


No Changes Required CONU_STANDARD has a numeric value of zero to insure 
compatibility with pre-V36 applications. CONU_LIBRARY has a numeric value of 
negative one and is also compatible with pre-V36 applications. 


Console device flags: 
e CONFLAG_DEFAULT - The console device will redraw the window when it is resized. 


e CONFLAG_NODRAW_ON_NEWSIZE -— The console device will not redraw the window 
when it is resized 


The character map units, CONU_CHARMAP and CONU_SNIPMAP, are the only units which use 
the flags parameter to set how the character map is used. CONU_STANDARD units ignore the 
flags parameter. 


See the include file devices/conunit.h for the flag definitions and the Amiga ROM Kernel Reference 
Manual: Includes and Autodocs for an explanation of the flags. 


64 Amiga ROM Kernel Reference Manual: Devices 


struct MsgPort *ConsoleMP; /* Message port pointer */ 
struct IOStdReq *ConsIO; /* I/O structure pointer */ 
struct Window *win = NULL; /* Window pointer */ 


struct NewWindow nw = 


10, 10, /* starting position (left,top) */ 
620,180, /* width, height */ 

-1,-1, /* detailpen, blockpen */ 
CLOSEWINDOW, /* flags for idemp */ 


WINDOWDEPTH | WINDOWSIZING| 
WINDOWDRAG | WINDOWCLOSE | 


SIMPLE REFRESH|ACTIVATE, /* window flags */ 

NULL, /* no user gadgets */ 

NULL, /* no user checkmark */ 
"Console Test", /* title */ 

NULL, /* pointer to window screen */ 
NULL, /* pointer to super bitmap */ 
100,45, /* min width, height */ 
640,200, /* max width, height */ 
WBENCHSCREEN /* open on workbench screen */ 


/* Create reply port console */ 
if (!(ConsoleMP = CreatePort ("RKM.Console",0))) 
cleanexit ("Can’t create write port\n",RETURN FAIL); 


/* Create message block for device I/O */ 
if (!(ConsIO = CreateExtIO(ConsoleMP, sizeof (struct IOStdReq) ))) 
cleanexit ("Can’t create IORequest\n",RETURN FAIL); 


/* Open a window --- we assume intuition.library is already open */ 
if (! (win = OpenWindow (&nw) )) 

cleanexit ("Can’t open window\n",RETURN_ FAIL); 

/* Set window pointer and size in I/O request */ 
ConsIO->io Data = (APTR) win; 
ConsI0O->io Length = sizeof (struct Window); 

/* Open the console device */ 


if (error = OpenDevice ("console.device",CONU_CHARMAP,ConsI0O,CONFLAG DEFAULT) ) 
cleanexit ("Can’t open console.device\n", RETURN FAIL); 


CLOSING THE CONSOLE DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIO(O. 


if (! (CheckIO(ConsIO) )) 


AbortIO(ConsI0O) ; /* Ask device to abort any pending requests */ 
WaitIO(ConsI0) ; /* Wait for abort, then clean up */ 
CloseDevice (ConsIO); /* Close console device */ 


Console Device 65 


About Console I/O 


The console device may be thought of as a kind of terminal. You send character streams to the 
console device; you also receive them from the console device. These streams may be characters, 
control sequences or a combination of the two. 


Console I/O is closely associated with the Amiga Intuition interface; a console must be tied to a 
window that is already opened. From the Window data structure, the console device determines 
how many characters it can display on a line and how many lines of text it can display in a window 
without clipping at any edge. 


You can open the console device many times, if you wish. The result of each open call is a new 
console unit. AmigaDOS and Intuition see to it that only one window is currently active and its 
console, if any, is the only one (with a few exceptions) that receives notification of input events, 
such as keystrokes. Later in this chapter you will see that other Intuition events can be sensed by 
the console device as well. 


Introducing... For this entire chapter the characters ““<CSI>” represent the control se- 
quence introducer. For output you may use either the two-character sequence <Esc>[ 
(0x1B OxSB) or the one-byte value 0x9B. For input you will receive 0x9B unless the 
sequence has been typed by the user. 


EXEC FUNCTIONS AND THE CONSOLE DEVICE 


The various Exec functions such as DoIO(Q), SendIOQ, AbortIO(Q) and CheckIOQ operate normally. 
The only caveats are that CMD_WRITE may cause your application to wait intemally, even with 
SendIOQ, and a task using CMD_READ to wait on a response from a console is at the user’s 
mercy. If the user never reselects that window, and the console response provides the only wake-up 
call, that task will sleep forever. 


GENERAL CONSOLE SCREEN OUTPUT 


Console character screen output (as compared to console command sequence transmission) outputs 
all standard printable characters (character values hex 20 through 7E and AO through FF) normally. 


Many control characters such as BACKSPACE (0x8) and RETURN (0x13) are translated into their 
exact ANSI equivalent actions. The LINEFEED character (OxA) is a bit different in that it can be 
translated into a RETURN/LINEFEED action. The net effect is that the cursor moves to the first 
column of the next line whenever an <LF> is displayed. This option is set via the mode control 
sequences discussed under “Control Sequences for Window Output.” 


CONSOLE KEYBOARD INPUT 


If you read from the console device, the keyboard inputs are preprocessed for you and you will get 
ASCII characters, such as “B.” Most normal text-gathering programs will read from the console 
device in this manner. Some programs may also ask to receive raw events in their console stream. 
Keypresses are converted to ASCII characters or CSI sequences via the keymap associated with the 
unit. 


66 Amiga ROM Kernel Reference Manual: Devices 


Writing to the Console Device 


You write to the console device by passing an I/O request to the device with a pointer to the write 
buffer set in io_Data, the number of bytes in the buffer set in io_Length and CMD_WRITE set in 
io_Command. 


UBYTE *outstring= "Make it so."; 


ConsI0->io Data = outstring; 
ConsI0->io Length = strlen(outstring); 
ConsI0O->io Command = CMD_WRITE; 
DoIO(ConsI0O); 


You may also send NULL-terminated strings to the console device in the same manner except that 
io_Length must be set to -1. 

ConsI0O->io_ Data = "\033[3mO0h boy."; 

ConsI0O->io Length = -1; 


ConsI0->io Command = CMD WRITE; 
DoIO(ConsI0) ; 


The fragment above will output the string "Oh boy.” in italics. Keep in mind that setting the text 
rendition to italics will remain in effect until you specifically instruct the console device to change 
it to another text style. 


HINTS FOR WRITING TEXT 


256 Is A Nice Round Number 
You must keep in mind that the console device locks all layers while writing text. To avoid, 
problems with this, it is best to send smaller rather larger numbers of character to be written. 
We recommend no more than 256 bytes per write as the optimum size 


Turn Off The Cursor 
If your console is attached to a V1.2/1.3 SuperBitmap window, you will not see a cursor 
rendered. For output speed and compatibility with future OS versions which may visibly 
render the cursor, you should send the cursor-off sequence (ESC[O p) whenever you open or 
reset (ESCc) a SuperBitmap window’s console. 


CONTROL SEQUENCES FOR WINDOW OUTPUT 


The following table lists functions that the console device supports, along with the character stream 
that you must send to the console to produce the effect. For more information on the control 
sequences, consult the console.doc of the Amiga ROM Kernel Reference Manual: Includes and 
Autodocs. The table uses the second form of <CSI>, that is, the hex value 0x9B, to minimize the 
number of characters to be transmitted to produce a function. 


A couple of notes about the table. If an item is enclosed in square brackets, it is optional and may be 
omitted. For example, for INSERT [N] CHARACTERS the value for N is shown as optional. The 
console device responds to such optional items by treating the value of N as 1 if it is not specified. 
The value of N or M is always a decimal number, having one or more ASCII digits to express its 
value. 


Console Device 67 


ANSI Console Control Sequences 


Console Command Sequence of Characters 
(in Hexadecimal Form) 

BELL 07 

(Flash the display—do an Intuition DisplayBeep()) 

BACKSPACE 08 

(move left one column) 

HORIZONTAL TAB 09 

(move right one tab stop) 

LINEFEED OA 

(move down one text line as specified by the mode function) 

VERTICAL TAB OB 

(move up one text line) 

FORMFEED OC 

(clear the console’s window) 

CARRIAGE RETURN OD 

(move to first column) 

SHIFT IN OE 

(undo SHIFT OUT) 

SHIFT OUT OF 

(set MSB of each character before displaying) 

ESC 1B 

(escape; can be part of the control sequence introducer) 

INDEX 84 

(move the active position down one line) 

NEXT LINE 85 

(go to the beginning of the next line) 

HORIZONTAL TABULATION SET 88 

(Set a tab at the active cursor position) 

REVERSE INDEX 8D 

(move the active position up one line) 

CSI 9B 

(control sequence introducer) 

RESET TO INITIAL STATE 1B 63 

INSERT [N] CHARACTERS 9B [N] 40 

(insert one or more spaces, shifting the remainder of the 

line to the right) 

CURSOR UP [N] CHARACTER POSITIONS 9B [N] 41 

(default = 1) 

CURSOR DOWN [N] CHARACTER POSITIONS 9B [N] 42 

(default = 1) 

CURSOR FORWARD [N] CHARACTER POSITIONS OB [N] 43 

(default = 1) 

CURSOR BACKWARD [N] CHARACTER OB [N] 44 


(default = 1) 


68 Amiga ROM Kernel Reference Manual: Devices 


CURSOR NEXT LINE [N] 

(to column 1) 

CURSOR PRECEDING LINE [N] 

(to column 1) 

CURSOR POSITION 

(where N is row, M is column, and semicolon (hex 3B) 
must be present as a separator, or if row is left out, so the 
console device can tell that the number after the semicolon 
actually represents the column number) 

CURSOR HORIZONTAL TABULATION 

(move cursor forward to Nth tab position) 

ERASE IN DISPLAY 

(only to end of display) 

ERASE IN LINE 

(only to end of line) 

INSERT LINE 

(above the line containing the cursor) 

DELETE LINE 

(remove current line, move all lines up one position to fill 
gap, blank bottom line) 

DELETE CHARACTER [N] 

(that cursor is sitting on and to the right if [N] is specified) 
SCROLL UP [N] LINES 

(Remove line(s) from top of window, move all other lines 
up, blanks [N] bottom lines) 

SCROLL DOWN [N] LINES 

(Remove line(s) from bottom of window, move all other 
lines down, blanks [N] top lines) 

CURSOR TABULATION CONTROL 

(where N = 0 set tab, 2 = clear tab, 5 = clear all tabs.) 
CURSOR BACKWARD TABULATION 

(move cursor backward to Nth tab position.) 

SET LINEFEED MODE 

(cause LINEFEED to respond as RETURN-LINEFEED) 
RESET NEWLINE MODE 

(cause LINEFEED to respond only as LINEFEED) 
DEVICE STATUS REPORT 

(cause console device to insert a CURSOR POSITION 
REPORT into your read stream ; see “Reading from the 
Console Device” for more information) 


SELECT GRAPHIC RENDITION 
(select text style, character color, character cell color, 
background color) 


9B [N] 45 
9B [N] 46 


9B [N] [3B M] 48 


9B [N] 49 
9B 4A 
9B 4B 
9B 4C 


9B 4D 


9B [N] 50 


9B [N] 53 


OB [N] 54 


9B [N] 57 
9B [N] 5A 
9B 32 30 68 
9B 32 30 6C 


9B 36 6E 


OB N 3B 3N 3B 4N 3B >N 6D 
See note below. 


Console Device 69 


For SELECT GRAPHIC RENDITION, any number of parameters, in any order, are valid. They 
are separated by semicolons. 


The parameters follow: 


<text style> = 
0 Plain text 8 Concealed mode 
1 Boldface 22 Normal color, not bold (V36) 
2 faint (secondary color) 23 Italic off (V36) 
3 Italic 24 Underscore off (V36) 
4 Underscore 27 Reversed off (V36) 
7 Reversed character/cell colors 28 Concealed off (V36) 


<character color> = 


30-37 System colors 0-7 for character color. 
39 Reset to default character color 
Transmitted as two ASCII characters. 


<character cell color> = 


40-47 System colors 0-7 for character cell color. 
39 Reset to default character color 
Transmitted as two ASCII characters. 


<background color> = 


>0-7 System colors 0-7 for background color. (V36) 
You must specify the “>” in order for this to be recognized 
and it must be the last parameter. 


For example, to select bold face, with color 3 as the character color, and color 0 as the character cell 
color and the background color, send the hex sequence: 
9B 31 3B 33 33 3B 34 30 3B 3E 30 6D 
representing the ASCII sequence: 
<CSI>1;33;40;>0m 
where <CSI> is the control sequence introducer, here used as the single character value Ox9B. 


Go Easy On The Eyes. In most cases, the character cell color and the background color 
should be the same. 


Set Graphic Rendition Implementation Notes 


Previous versions of the operating system did not support the global background color sequence as 
is listed above. Instead, the background color was set by setting the character cell color and then 
clearing the screen (e.g., a FORMFEED). 


In fact, vacated areas of windows (vacated because of an ERASE or SCROLL) were filled in with 
the character cell color. This is no longer the case. Now, when an area is vacated, it is filled in with 
the global background color. 


70 Amiga ROM Kernel Reference Manual: Devices 


SMART_REFRESH windows are a special case: 


Under V33-V34: 
The cell color had to be set and a FORMFEED (clear window) needed to be sent on resize or 
immediately to clear the window and set the background color. 


For example, if you took a CLI window and sent the sequence to set the cell color to something 
other than the default, the background color would not be changed immediately (contrary to 
what was expected). 


If you then sent a FORMFEED, the background color would change, but if you resized the 
window larger, you would note that the newly revealed areas were filled in with PEN 0. 


Under V36-V37 (non-character mapped): 
You need to set the global background color and do a FormFeed. The background color will 
then be used to fill the window, but like V33-V34, if you make the window larger, the vacated 
areas will be filled in with PEN 0. 


Under V36—V37 (character mapped): 
You need to set the global background color, the window is redrawn immediately (because we 
have the character map) and will be correctly redrawn with the global background color on 
subsequent resizes. 


The sequences in the next table are not ANSI standard sequences, they are private Amiga sequences. 


In these command descriptions, length, width, and offset are comprised of one or more ASCII digits, 
defining a decimal value. 


Amiga Console Control Sequences 


Console Command Sequence of Characters 
(in Hexadecimal Form) 

ENABLE SCROLL OB 3E 31 68 

(this is the default) 

DISABLE SCROLL 9B 3E 31 6C 

AUTOWRAP ON 9B 3F 37 68 

(the default) 

AUTOWRAP OFF 9B 3F 37 6C 

SET PAGE LENGTH 9B <length> 74 


(in character raster lines, causes console to recalculate, 

using current font, how many text lines will fit on the 

page) 

SET LINE LENGTH 9B <width> 75 
(in character positions, using current font, how many char- 

acters should be placed on each line) 

SET LEFT OFFSET 9B <offset> 78 
(in raster columns, how far from the left of the window 

should the text begin) 


Console Device 71 


SET TOP OFFSET 

(in raster lines, how far from the top of the window’s 
RastPort should the topmost line of the character begin) 
SET RAW EVENTS 

(set the raw input events that will trigger an INPUT 
EVENT REPORT. see the “Selecting Raw Input Events” 
section below for more details.) 

INPUT EVENT REPORT 

(returned by the console device in response to a raw event 
set by the SET RAW EVENT sequence. see the “Input 
Event Reports” section below for more details.) 

RESET RAW EVENTS 

(reset the raw events set by the SET RAW EVENT se- 
quence. see the “Selecting Raw Input Events” section 
below.) 

SPECIAL KEY REPORT 

(retumed by the console device whenever HELP, or one 
of the function keys or arrow keys is pressed. Some se- 
quences do not end with 7E) 

SET CURSOR RENDITION 

(make the cursor visible or invisible: Note—tuming off 


the cursor increases text output speed) 
Invisible: 
Visible: 


WINDOW STATUS REQUEST 

(ask the console device to tell you the current bounds of 
the window, in upper and lower row and column character 
positions. User may have resized or repositioned it. See 
“Window Bounds Report” below.) 

WINDOW BOUNDS REPORT 

(returned by the console device in response toa WINDOW 
STATUS REQUEST sequence) 

RIGHT AMIGA V PRESS 

(retumed by the console device when the user presses 
RIGHT-AMIGA-V. See the “Copy and Paste Support” 
section below for more details.) 


9B <offset> 79 


OB <events> 7B 


9B <parameters> 7C 


9B <events> 7D 


9B <keyvalue> 7E 


9B N 20 70 


9B 30 20 70 
9B 20 70 


9B 30 20 71 


9B 31 3B 31 3B <bot margin> 
3B <right margin> 72 


9B 30 20 76 


Give Back What You Take. The console device normally handles the SET PAGE 
LENGTH, SET LINE LENGTH, SET LEFT OFFSET, and SET TOP OFFSET functions 
automatically. To allow it to do so again after setting your own values, send the functions 


without a parameter. 


72 Amiga ROM Kernel Reference Manual: Devices 


EXAMPLE CONSOLE CONTROL SEQUENCES 


Move cursor right by 1: 
Character string equivalents: 
<CSI>C or 
<CSI>1C 
Numeric (hex) equivalents: 
OB 43 
OB 31 43 


Move cursor right by 20: 


Character string equivalent: 
<CSI>20C 

Numeric (hex) equivalent: 
9B 32 30 43 


Move cursor to upper-left comer (home): 


Character string equivalents: 
<CSI>H or 
<CSI>1;1H or 
<CSI>;1H or 
<CSI>1;H 

Numeric (hex) equivalents: 
OB 48 
9B 31 3B 31 48 
OB 3B 31 48 
OB 31 3B 48 


Move cursor to the fourth column of the first line of the window: 
Character string equivalents: 
<CSI>1;4H or 
<CSI>;4H 
Numeric (hex) equivalents: 
OB 31 3B 34 48 
OB 3B 34 48 


Clear the window: 


Character string equivalents: 
<FF> or CTRL-L (clear window) or 
<CSI>H<CSI>J (home and clear to end of window) 
Numeric (hex) equivalents: 


9B 48 9B 4A 


Console Device 73 


Reading from the Console Device 


Reading input from the console device returns an ANSI 3.64 standard byte stream. This stream 
may contain normal characters and/or RAW input event information. You may also request other 
RAW input events using the SET RAW EVENTS and RESET RAW EVENTS control sequences 
discussed below. See “Selection of Raw Input Events.” 


Generally, console reads are performed asynchronously so that your program can respond to other 
events and other user input (such as menu selections) when the user is not typing on the keyboard. To 
perform asynchronous I/O, an I/O request is sent to the console using the SendIO() function (rather 
than a synchronous DoIOQ which would wait until the read request returned with a character). 


You read from the console device by passing an I/O request to the device with a pointer to the read 
buffer set in io_Data, the number of bytes in the buffer set in io_Length and CMD_READ set in 
io_Command. 


#define READ BUFFER SIZE 25 
char ConsoleReadBuffer[READ_BUFFER_SIZE]; 


ConsI0O->io Data = (APTR)ConsoleReadBuf fer; 
ConsI0->io Length = READ_BUFFER_SIZE; 
ConsI0->io Command = CMD_READ; 
SendIO(ConsI0O) ; 


You May Get Less Than You Bargained For. A request for more than one character 
may be satisfied by the receipt of only one character. If you request more than one character, 
you will have to examine the io_Actual field of the request when it returns to determine 
how many characters you have actually received. 


After sending the read request, your program can wait on a combination of signal bits including 
that of the reply port you created. The following fragment demonstrates waiting on both a queued 
console read request, and Window IDCMP messages: 


ULONG conreadsig = 1 << ConsoleMP->mp SigBit; 
ULONG windowsig = 1 << win->UserPort->mp_SigBit; 


/* A character, or an IDCMP msg, or both will wake us up */ 
ULONG signals = Wait(conreadsig | windowsig); 


if (signals & conreadsig) 


/* Then check for a character */ 


if (signals & windowsig) 


/* Then check window messages */ 
ie 


INFORMATION ABOUT THE INPUT STREAM 


For the most part, keys whose keycaps are labeled with ANSI-standard characters will ordinarily 
be translated into their ASCTI-equivalent character by the console device through the use of its 
keymap. Keymap information can be found in the ‘“‘Keymap Library” chapter of the Amiga ROM 
Kernel Reference Manual: Libraries. 


74 Amiga ROM Kernel Reference Manual: Devices 


For keys other than those with normal ASCII equivalents, an escape sequence is generated and 
inserted into your input stream. For example, in the default state (no raw input events selected) the 
function, arrow and special keys (reserved for 101 key keyboards) will cause the sequences shown 
in the next table to be inserted in the input stream. 


Special Key Report Sequences 


Key Unshifted Sends Shifted Sends 

Fl <CSI>0° <CSI>10~ 

F2 <CSI>1~ <CSI>117 

F3 <CSI>2° <CSI>127 

F4 <CSI>3~ <CSI>137 

F5 <CSI>4° <CSI>14" 

F6 <CSI>5~ <CSI>15° 

F7 <CSI>6" <CSI>16° 

F8 <CSI>7~ <CSI>17~ 

F9 <CSI>8" <CSI>18° 

F10. <CSI>9° <CSI>19° 

Fll <CSI>20~ <CSI>30" (101 key keyboard) 

F12 <CSI>21° <CSI>317 (101 key keyboard) 

HELP <CSI>7" <CSI>?7" (same sequence for both) 

Insert <CSI>40" <CSI>50" (101 key keyboard) 

Page Up <CSI>41° <CSI>51° (101 key keyboard) 

Page Down <CSI>42° <CSI>52" (101 key keyboard) 

Pause/Break <CSI>43° <CSI>537 (101 key keyboard) 

Home <CSI>44" <CSI>54- (101 key keyboard) 

End <CSI>45~ <CSI>55~ (101 key keyboard) 

Arrow keys: 

Up <CSI>A <CSI>T 

Down <CSI>B <CSI>S 

Left <CSI>D <CSI> A (notice the space 

Right <CSI>C <CSI> @ after <CSI>) 
CURSOR POSITION REPORT 


If you have sent the DEVICE STATUS REPORT command sequence, the console device retums a 
cursor position report into your input stream. It takes the form: 


<CSI><row>;<column>R 


For example, if the cursor is at column 40 and row 12, here are the ASCII values (in hex) you 
receive in a stream: 


9B 34 30 3B 31 32 52 


Console Device 75 


WINDOW BOUNDS REPORT 


A user may have either moved or resized the window to which your console is bound. By issuing 
a WINDOW STATUS REPORT to the console, you can read the current position and size in the 
input stream. This window bounds report takes the following form: 


<CSI>1;1;<bottom margin>;<right margin> r 


The bottom and right margins give you the window row and column dimensions as well. For a 
window that holds 20 lines with 60 characters per line, you will receive the following in the input 
stream: 


9B 31 3B 31 3B 32 30 3B 36 30 20 72 


Copy and Paste Support 


As noted above, opening the console device with a unit of CONU_SNIPMAP allows the user to 
drag-select text with the mouse and copy the selection with Right-Amiga-C. 


Internally, the snip is copied to a private buffer managed by the console device where it can be 
copied to other console device windows by pressing Right-Amiga-V. 


However, your application should assume that the user is running the “‘Conclip” utility which is 
part of the standard Workbench 2.0 environment. Conclip copies snips from the console device to 
the clipboard device where they can be used by other applications which support reading from the 
clipboard. 


When Conclip is running and the user presses Right-Amiga-V, the console device puts an escape 
sequence in your read stream—<CSI>0 v (Hex 9B 30 20 76)—which tells you that the user wants 
to paste text from the clipboard. 


Upon receipt of this sequence, your application should read the contents of the clipboard device, 
make a copy of any text found there and then release the clipboard so that it can be used by other 
applications. See the “Clipboard Device” chapter for more information on reading data from it. 


You paste what you read from the clipboard by using successive writes to the console. In order to 
avoid problems with excessively long data in the clipboard, you should limit the size of writes to 
something reasonable. (We define reasonable as no more than 1K per write with the ideal amount 
being 256 bytes.) You should also continue to monitor the console read stream for additional use 
input, paster requests and, possibly, RAW INPUT EVENTS while you are doing this. 


You should not open a character mapped console unit with COPY capability if you are unable to 
support PASTE from the clipboard device. The user will reasonably expect to be able to PASTE 
into windows from which a COPY can be done. 


Keep in mind that users do make mistakes, so an UNDO mechanism for aborting a PASTE is highly 
desirable—particularly if the user has just accidentally pasted text into an application like a terminal 
program which is sending data at a slow rate. 


Use CON:, You'll Be Glad You Did. It is highly recommended that you consider 
using the console-handler (CON:) if you want a console window with COPY and PASTE 
capablilities. CON: provides you with free PASTE support and is considerably easier to 
open and use than using the console device directly. 


76 Amiga ROM Kernel Reference Manual: Devices 


Selecting Raw Input Events 


If the keyboard information-including “cooked” keystrokes—does not give you enough information 
about input events, you can request additional information from the console driver. 


The command to SET RAW EVENTS is formatted as: 
<CSI>[event-types-separated-by-semicolons] { 


If, for example, you need to know when each key is pressed and released, you would request 
“RAW keyboard input.” This is done by writing “<CSI>1{” to the console. In a single SET RAW 
EVENTS request, you can ask the console to set up for multiple event types at one time. You 
must send multiple numeric parameters, separating them by semicolons (;). For example, to ask for 
gadget pressed, gadget released, and close gadget events, write: 


<CSI>7;8;11{ 


You can reset, that is, delete from reporting, one or more of the raw input event types by using the 
RESET RAW EVENTS command, in the same manner as the SET RAW EVENTS was used to 
establish them in the first place. This command stream is formatted as: 


<CSI>[event-types-separated-by-semicolons] } 


So, for example, you could reset all of the events set in the above example by transmitting the 
command sequence: 


<CSI>7;8;11} 


The Read Stream May Not Be Dry. There could still be pending RAW INPUT EVENTS 
in your read stream after turning off one or more RAW INPUT EVENTS. 


The following table lists the valid raw input event types. 


Raw Input Event Types 
Request Request 
Number Description Number Description 
0 No-op (used internally) 11 Close Gadget 
1 RAW keyboard input 12 Window resized 
Intuition swallows all 13 Window refreshed 
except the select button) 14 Preferences changed 
2 RAW mouse input 15 Disk removed 
3 Private Console Event 16 Disk inserted 
4 Pointer position 17 Active window 
5 (unused) 18 Inactive window 
6 Timer 19 New pointer position (V36) 
7 Gadget pressed 20 Menu help (V36) 
8 Gadget released 21 Window changed (V36) 
9 Requester activity (zoom, move) 
10 Menu numbers 


The event types—requester, window refreshed, active window, inactive window, window resized 
and window changed—are dispatched to the console unit which owns the window from which the 
events are generated, even if it is not the active (selected ) window at the time the event is generated. 
This ensures that the proper console unit is notified of those events. All other events are dispatched 
to the active console unit (if it has requested those events). 


Console Device 77 


Input Event Reports 


If you select any of these events you will start to get information about the events in the following 
form: 


<CSI><class>;<subclass>;<keycode>;<qualifiers>; <x>;<y>;<seconds>;<microseconds>| 


<CSI> 
is a one-byte field. It is the “control sequence introducer,” 0x9B in hex. 


<class> 
is the RAW input event type, from the above table. 


<subclass> 
is usually 0. If the mouse is moved to the right controller, this would be 1. 


<keycode> 
indicates which raw key number was pressed. This field can also be used for mouse information. 


The Raw Key Might Be The Wrong Key. National keyboards often have different 
keyboard arrangements. This means that a particular raw key number may represent 
different characters on different national keyboards. The normal console read stream 
(as opposed to raw events) will contain the proper ASCII character for the keypress as 
translated according to the user’s keymap. 


<qualifiers> 
indicates the state of the keyboard and system. 


The qualifiers are defined as follows: 


input Event Qualifiers 


Bit Mask Key 

0 0001 Left shift 

1 0002 Right shift 

2 0004 Caps Lock Associated keycode is special; see below. 
3 0008 Ctrl 

4 0010 Left Alt 

5 0020 Right Alt 

6 0040 Left Amiga key pressed 

7 0080 Right Amiga key pressed 

8 0100 Numeric pad 

9 0200 Repeat 

10 0400 Interrupt Not currently used. 

11 0800 Multibroadcast This window (active one) or all windows. 
12 1000 Middle mouse button (Not available on standard mouse) 


13 2000 Right mouse button 
14 4000 Left mouse button 
15 8000 Relative mouse Mouse coordinates are relative, not absolute. 


The Caps Lock key is handled in a special manner. It generates a keycode only when it is pressed, 
not when it is released. However, the up/down bit (80 hex) is still used and reported. If pressing 


78 Amiga ROM Kernel Reference Manual: Devices 


the Caps Lock key causes the LED to light, keycode 62 (Caps Lock pressed) is sent. If pressing 
the Caps Lock key extinguishes the LED, keycode 190 (Caps Lock released) is sent. In effect, the 
keyboard reports this key as held down until it is struck again. 


The <x> and <y> fields are filled by some classes with an Intuition address: x<<16+y. 


The <seconds> and <microseconds> fields contain the system time stamp taken at the time the 
event occurred. These values are stored as longwords by the system. 


With RAW keyboard input selected, keys will no longer retum a simple one-character “A” to “Z” 
but will instead return raw keycode reports of the form: 


<CSI>1;0;<keycode>;<qualifiers>;<prev1>;<prev2>;<seconds>;<microseconds>| 


For example, if the user pressed and released the A key with the left Shift and right Amiga keys 
also pressed, you might receive the following data: 


<CSI>1;0;32;32769; 14593;5889;42 1939940; 316673| 
<CSI>1;0; 160;32769;0;0;421939991;816683| 


The <keycode> field is an ASCII decimal value representing the key pressed or released. Adding 
128 to the pressed key code will result in the released keycode. 


The <prev1> and <prev2> fields are relevant for the interpretation of keys which are modifiable 
by dead-keys (see “Dead-Class Keys” section). The <prev1> field shows the previous key pressed. 
The lower byte shows the qualifier, the upper byte shows the key code. The <prev2> field shows 
the key pressed before the previous key. The lower byte shows the qualifier, the upper byte shows 
the key code. 


Using the Console Device Without a Window 


Most console device processing involves a window, but there are functions and special commands 
that may be used without a window. To use the console device without a window, you call 
OpenDevice() with the console unit CONU_LIBRARY. 


The console device functions are CDInputHandler() and RawKeyConvert(); they may only be 
used with the CONU_LIBRARY console unit. The console device commands which do not require 
a window are CD_ASKDEFAULTKEYMAP and CD_SETDEFAULTKEYMAP; they be used with 
any console unit. The advantage of using the commands with the CONU_LIBRARY unit is the 
lack of overhead required for CONU_LIBRARY because it doesn’t require a window. 
To use the functions requires the following steps: 

e Declare the console device base address variable ConsoleDevice in the global data area. 

e Declare storage for an I/O request of type IOStdReq. 

e Open the console device with CONU_LIBRARY set as the console unit. 


e Set the console device base address variable to point to the device library vector which is 
retumed in io_Device. 


e Call the console device function(s). 
e Close the console device when you are finished. 


Console Device 79 


#tinclude <devices/conunit.h> 


struct ConsoleDevice *ConsoleDevice; /* declare device base address */ 
struct IOStdReq ConsIO= {0}; /* I/O request */ 
main () 


/* Open the device with CONU_LIBRARY for function use */ 
if (0 == OpenDevice ("console.device",CONU_LIBRARY, (struct IORequest *) &ConsI0,0)) 
{ 


/* Set the base address variable to the device library vector */ 
ConsoleDevice = (struct ConsoleDevice *)ConsI0O.io Device; 


(console device functions would be called here) 


CloseDevice (ConsIO) ; 


} 


The code fragment shows only the steps outlined above, it is not complete in any sense of the word. 
For a complete example of using a console device function, see the rawkey.c code example in the 
“Intuition: Mouse and Keyboard” chapter of the Amiga ROM Kernel Reference Manual: Libraries. 
The example uses the RawKeyConvert() function. 


To use the commands with the CONU_LIBRARY console unit, you follow the same steps that were 
outlined in the “Opening the Console Device” section of this chapter. 


struct MsgPort *ConsoleMP; /* pointer to our message port */ 
struct IOStdReq *ConsoleI0O; /* pointer to our I/O request */ 
struct KeyMap *keymap; /* pointer to keymap */ 


/* Create the message port */ 
if (ConsoleMP=CreateMsgPort () ) 
{ 
/* Create the I/O request */ 
if (ConsoleIO = CreateIORequest (ConsoleMP, sizeof (struct IOStdReq) ) ) 
{ 


/* Open the Console device */ 
if (OpenDevice ("console.device",CONU_LIBRARY, (struct IORequest *)ConsoleIO, 0L)) 


/* Inform user that it could not be opened */ 
printf("Error: console.device did not open\n"); 
else 


/* Allocate memory for the keymap */ 
if (keymap = (struct KeyMap *) 
AllocMem(sizeof (struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR) ) 
{ 


/* device opened, send CD_ASKKEYMAP command to it */ 
ConsoleIO->io Length = sizeof(struct KeyMap) ; 

ConsoleIO->io Data = (APTR) keymap; /* where to put it */ 
ConsoleIO->io Command = CD_ASKKEYMAP; 

DoIO((struct IORequest *)ConsoleI0O) ) 

} 


CloseDevice (ConsIO); 


Again, as in the previous code fragment, this is not complete (that’s why it’s a fragment!) and you 
should only use it as a guide. 


80 Amiga ROM Kernel Reference Manual: Devices 


Where Is All the Keymap Information? 


Unlike previous editions of this chapter, this one has a very small amount of keymap information. 
Keymap information is now contained, appropriately enough, in the “Keymap Library” chapter of 
the Amiga ROM Kernel Reference Manual: Libraries. 


Console Device Caveats 
e Only one console unit can be attached per window. Sharing a console window must be done at 
a level higher than the device. 


e Do not mix graphics.library calls with console rendering in the same areas of a window. It 
is permissible to send console sequences to adjust the area in which console renders, and use 
graphics.library calls to render outside of the area console is using. 


For example, do not render text with console sequences and scroll using the graphics.library 
ScrollRaster() function. 


e The character map feature is private and cannot be accessed by the programmer. Implementation 
details and behaviors of the character map my change in the future. 


e Do not use an IDCMP with character mapped consoles. All Intuition messages should be 
obtained via RAW INPUT EVENTS from the console device. 


Console Device Example Code 


The following is a console device demonstration program with supporting routines: 


/* 

* Console.c 

* 

* Example of opening a window and using the console device 
* to send text and control sequences to it. The example can be 
* easily modified to do additional control sequences. 

* 

* Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 

* 

* Run from CLI only. 

* 


/ 


#include <exec/types.h> 

#include <exec/io.h> 

#include <exec/memory.h> 
#include <intuition/intuition.h> 
#include <libraries/dos.h> 
#include <devices/console.h> 


#include <clib/exec_protos.h> 
#include <clib/alib_ protos.h> 
#include <clib/dos_protos.h> 
#include <clib/intuition_protos.h> 
#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#endif 


Console Device 81 


/* Note - using two character <CSI> ESC[. Hex 9B could be used instead */ 
#define RESETCON "\033c" 

#define CURSOFF "\033[0 p" 

#define CURSON "\033[ p" 

#define DELCHAR "\033(P" 


* SGR (set graphic rendition) */ 
#define COLOR02 "\033[32m" 
#define COLORO3 "\033[(33m" 
#define ITALICS "\033[3m" 


#define BOLD "\033(1m" 
#define UNDERLINE "\033(4m" 
#define NORMAL "\033[0m" 


/* our functions */ 

void cleanexit (UBYTE *, LONG); 

void cleanup (void); 

BYTE OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *); 
void CloseConsole(struct IOStdReq *); 

void QueuveRead(struct IOStdReq *, UBYTE *); 
UBYTE ConGetChar(struct MsgPort *, UBYTE *); 
LONG ConMayGetChar (struct MsgPort *, UBYTE *); 
void ConPuts(struct IOStdReq *, UBYTE *); 

void ConWrite(struct IOStdReq *, UBYTE *, LONG); 
void ConPutChar(struct I0StdReq *, UBYTE); 

void main(int argc, char **argv); 

struct NewWindow nw = 


10, 10, /* starting position (left,top) */ 
620,180, /* width, height */ 

-1,-1, /* detailpen, blockpen */ 
CLOSEWINDOW, /* flags for idcmp */ 


WINDOWDEPTH | WINDOWSIZING| 
WINDOWDRAG | WINDOWCLOSE | 


SMART_REFRESH|ACTIVATE, /* window flags */ 

NULL, /* no user gadgets */ 

NULL, /* no user checkmark */ 
"Console Test", /* title */ 

NULL, /* pointer to window screen */ 
NULL, /* pointer to super bitmap */ 
100,45, /* min width, height */ 
640,200, /* max width, height */ 
WBENCHSCREEN /* open on workbench screen */ 


he 


/* Opens/allocations we’ll need to clean up */ 
struct Library *IntuitionBase = NULL; 
struct Window *win = NULL; 


struct IO0StdReq *writeReq = NULL; /* IORequest block pointer */ 
struct MsgPort *writePort = NULL; /* replyport for writes mf 
struct IOStdReq *readReq = NULL; /* TORequest block pointer */ 
struct MsgPort *readPort = NULL; /* replyport for reads */ 


BOOL OpenedConsole = FALSE; 
BOOL FromWb; 


void main(argce, argv) 
int argc; 
char **argv; 


struct IntuiMessage *winmsg; 

ULONG signals, conreadsig, windowsig; 
LONG lch; 

SHORT InControl = 0; 

BOOL Done = FALSE; 

UBYTE ch, ibuf; 

UBYTE obuf [200]; 

BYTE error; 


FromWb = (argc==0L) ? TRUE : FALSE; 


if (! (IntuitionBase=OpenLibrary ("intuition. library", 0))) 
cleanexit ("Can’t open intuition\n",RETURN_FAIL); 


/* Create reply port and io block for writing to console */ 


82 Amiga ROM Kernel Reference Manual: Devices 


if(! (writePort = CreatePort ("RKM.console.write",0))) 
cleanexit ("Can’t create write port\n",RETURN_FAIL); 


if(! (writeReq = (struct IO0StdReq *) 
CreateExtIO(writePort, (LONG) sizeof (struct IOStdReq) ))) 
cleanexit ("Can’t create write request\n", RETURN FAIL); 


/* Create reply port and io block for reading from console */ 
if(!(readPort = CreatePort ("RKM.console. read", 0) )) 
cleanexit ("Can’t create read port\n",RETURN FAIL); 


if(! (readReq = (struct IOStdReq *) 
CreateExtIO(readPort, (LONG) sizeof (struct IOStdReq) ))) 
cleanexit ("Can’t create read request\n",RETURN FAIL); 


/* Open a window */ 
if(! (win = OpenWindow (&nw) )) 
cleanexit ("Can’t open window\n", RETURN FAIL); 


/* Now, attach a console to the window */ 
if(error = OpenConsole (writeReq, readReq, win) ) 

cleanexit ("Can’t open console.device\n", RETURN FAIL); 
else OpenedConsole = TRUE; 


/* Demonstrate some console escape sequences */ 

ConPuts (writeReq, "Here’s some normal text\n"); 

sprintf (obuf,"%s%sHere’s text in color 3 and italics\n",COLORO3, ITALICS); 
ConPuts (writeReq, obuf) ; 

ConPuts (writeReq, NORMAL) ; 

Delay (50); /* Delay for dramatic demo effect */ 
ConPuts (writeReq,"We will now delete this asterisk =*="); 
Delay (50); 

ConPuts (writeReq,"\b\b"); /* backspace twice */ 

Delay (50); 

ConPuts (writeReq, DELCHAR); /* delete the character */ 
Delay (50); 


QueueRead (readReq, &ibuf); /* send the first console read request */ 


ConPuts (writeReq,"\n\nNow reading console\n"); 
ConPuts (writeReq,"Type some keys. Close window when done.\n\n"); 


conreadsig = 1 << readPort->mp_SigBit; 
windowsig = 1 << win->UserPort->mp_SigBit; 


while (!Done) 


/* A character, or an IDCMP msg, or both could wake us up */ 
signals = Wait (conreadsig|windowsig) ; 


/* If a console signal was received, get the character */ 
if (signals & conreadsig) 


{ 
if((lch = ConMayGetChar(readPort,&ibuf)) != -1) 
{ 


ch = lech; 
/* Show hex and ascii (if printable) for char we got. 

* If you want to parse received control sequences, such as 
function or Help keys, you would buffer control sequences 
as you receive them, starting to buffer whenever you 
receive 0x9B (or Ox1B[{ for user-typed sequences) and 
ending when you receive a valid terminating character 
for the type of control sequence you are receiving. 

For CSI sequences, valid terminating characters 

are generally 0x40 through Ox7E. 

In our example, InControl has the following values: 

0 no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [, 

3 now inside control sequence, -1 = normal end esc, 
-2 = non-CSI(no [) 0x1B end esc 

NOTE - a more complex parser is required to recognize 
other types of control sequences. 


/ 


/* 0x1B ESC not followed by ’[’, is not CSI seq */ 
if (InControl==1) 


4% ob Oe He OE 


{ 
if(ch=='[(’) InControl = 2; 


Console Device 83 


else InControl = -2; 


} 


if ((ch==0x9B) || (ch==0x1B)) /* Control seq starting */ 
{ 


InControl = (ch==0x1B) ? 1: 2; 
ConPuts (writeReq, "=== Control Seq ===\n"); 


} 


/* We'll show value of this char we received */ 

if (((ch >= Ox1F)&&(ch <= Ox7E)) || (ch >= 0xA0)) 
sprintf (obuf,"Received: hex %02x = %c\n",ch,ch); 

else sprintf (obuf, "Received: hex %02x\n", ch); 

ConPuts (writeReq, obuf) ; 


/* Valid ESC sequence terminator ends an ESC seq */ 
if ((InControl==3) &&((ch >= 0x40) && (ch <= Ox7E))) 


{ 
InControl = -1; 


} 
if (InControl==2) InControl = 3; 
/* ESC sequence finished (-1 if OK, -2 if bogus) */ 
if (InControl < 0) 

{ 

InControl = 0; 

ConPuts (writeReq, "=== End Control ===\n"); 


} 
} 


/* If IDCMP messages received, handle them */ 
if (signals & windowsig) 


{ 
/* We have to ReplyMsg these when done with them */ 


while (winmsg = (struct IntuiMessage *)GetMsg(win->UserPort) ) 


switch (winmsg->Class) 


case CLOSEWINDOW: 
Done = TRUE; 
break; 
default: 
break; 
} 
ReplyMsg((struct Message *)winmsg) ; 
} 


} 


/* We always have an outstanding queued read request 
* so we must abort it if it hasn’t completed, 
* and we must remove it. 


*/ 
if (! (CheckIO(readReq))) AbortIO(readReq) ; 
WaitI0O(readReq) ; /* clear it from our replyport */ 


cleanup (); 
exit (RETURN_OK); 
} 


void cleanexit (UBYTE *s,LONG n) 
{ 
if(*s & (!FromWb)) printf (s); 
cleanup(); 
exit (n); 
} 


void cleanup () 


if (OpenedConsole) CloseConsole (writeReq) ; 


if (readReq) DeleteExtI0O(readReq) ; 
if (readPort) DeletePort (readPort) ; 
if (writeReq) DeleteExtIO(writeReq) ; 
if (writePort) DeletePort (writePort) ; 
if (win) CloseWindow (win); 


if (IntuitionBase) CloseLibrary (IntuitionBase) ; 


} 


84 Amiga ROM Kernel Reference Manual: Devices 


/* Attach console device to an open Intuition window. 
* This function returns a value of 0 if the console 
* device opened correctly and a nonzero value (the error 
* returned from OpenDevice) if there was an error. 
*/ 
BYTE OpenConsole(writereq, readreq, window) 
struct I0StdReq *writereq; 
struct I0StdReq *readreq; 
struct Window *window; 


BYTE error; 


writereq->io_Data = (APTR) window; 

writereq->io_Length = sizeof(struct Window); 

error = OpenDevice("console.device", 0, writereq, 0); 

readreq->io_ Device = writereq->io Device; /* clone required parts */ 
readreq->io Unit = writereq->io Unit; 

return (error); 


} 
void CloseConsole(struct IO0StdReq *writereq) 
{ 


CloseDevice (writereq) ; 


} 
/* Output a single character to a specified console 
*/ 
void ConPutChar (struct I0StdReq *writereq, UBYTE character) 


{ 

writereq->io Command = CMD WRITE; 

writereq->io Data = (APTR) &character; 

writereq->io Length = 1; 

DoIO(writereq) ; 

/* command works because DoIO blocks until command is done 
* (otherwise ptr to the character could become invalid) 
*/ 


} 


/* Output a stream of known length to a console 
*/ 
void ConWrite(struct I0StdReq *writereq, UBYTE *string, LONG length) 


{ 

writereq->io_ Command = CMD_WRITE; 

writereq->io_Data = (APTR) string; 

writereq->io_Length = length; 

DolO(writereq) ; 

/* command works because DoIO blocks until command is done 
* (otherwise ptr to string could become invalid in the meantime) 
*/ 

} 


/* Output a NULL-terminated string of characters to a console 
*/ 
void ConPuts(struct IO0StdReq *writereq, UBYTE *string) 


{ 

writereq->io_Command = CMD_WRITE; 

writereq->io Data = (APTR) string; 

writereq->io Length = -1; /* means print till terminating null */ 
DolO(writereq) ; 


/* Queue up a read request to console, passing it pointer 
* to a buffer into which it can read the character 
*/ 
void QueueRead (struct IOStdReq *readreq, UBYTE *whereto) 
{ 


readreq->io_Command = CMD_READ; 
readreq->io Data = (APTR)whereto; 
readreq->io Length = 1; 

SendIO (readreq) ; 

} 


Console Device 85 


/* Check if a character has been received. 
* If none, return -1 
*/ 
LONG ConMayGetChar (struct MsgPort *msgport, UBYTE *whereto) 
{ 


register temp; 
struct IO0StdReq *readreq; 


if (!(readreq = (struct IOStdReq *)GetMsg(msgport))) return(-1); 
temp = *whereto; /* get the character */ 

QueueRead (readreq, whereto) ; /* then re-use the request block */ 
return (temp) ; 


/* Wait for a character 
*/ 
UBYTE ConGetChar (struct MsgPort *msgport, UBYTE *whereto) 
{ 


register temp; 
struct IO0StdReq *readreq; 


WaitPort (msgport) ; 

readreq = (struct IOStdReq *)GetMsg(msgport); 

temp = *whereto; /* get the character */ 

QueueRead (readreq, whereto) ; /* then re-use the request block*/ 
return ( (UBYTE) temp) ; 

} 


Additional Information on the Console Device 


Additional programming information on the console device can be found in the include files and the 
Autodocs for the console device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Console Device Information 


INCLUDES devices/console.h 
devices/console.i 


devices/conunit.h 
devices/conunit.i 


AUTODOCS console.doc 





86 Amiga ROM Kernel Reference Manual: Devices 


chapter five 
GAMEPORT DEVICE 


The gameport device manages access to the Amiga gameport connectors for the operating system. 
It enables the Amiga to interface with various extemal pointing devices like mice (two and three 
button), joysticks, trackballs and light pens. There are two units in the gameport device, unit 0 and 
unit 1. 


Amiga Gameport Connectors 


Front Connector Back Connector 


Left Connector Right Connector 


1 Z 


1 JOYSTICK 2 JOYSTICK 





Gameport Device 87 


Gameport Device Commands and Functions 


Command 


CMD_CLEAR 
GPD_ASKCTYPE 
GPD_ASKTRIGGER 
GPD_READEVENT 
GPD_SETCTYPE 
GPD_SETTRIGGER 


Operation 


Clear the gameport input buffer. 

Retum the type of gameport controller being used. 
Retum the conditions that have been preset for triggering. 
Read one or more gameport events. 

Set the type of the controller to be used. 

Preset the conditions that will trigger a gameport event. 


Exec Functions as Used In This Chapter 


AbortIOQ 
CheckIOQ 
CloseDevice() 


DoIOQ 
OpenDevice() 


SendIOQ 
WaitlO( 


Abort a command to the gameport device. 

Retur the status of an I/O request. 

Relinquish use of the gameport device. All requests must be complete 
before closing. 

Initiate a command and wait for completion (synchronous request). 
Obtain shared use of one unit of the gameport device. The unit number 
specified is placed in the I/O request structure for use by gameport 
commands. 

Initiate a command and return immediately (asynchronous request). 
Wait for the completion of an asynchronous request. When the request 
is complete the message will be removed from reply port. 


Exec Support Functions as Used in This Chapter 


CreateExtIO() 


CreatePort() 


DeleteExtIO() 
DeletePort() 


Create an extended I/O request structure of type I[OStdReq. This 
structure will be used to communicate commands to the gameport 
device. 

Create a signal message port for reply messages from the gameport 
device. Exec will signal a task when a message arrives at the port. 
Delete an I/O request structure created by CreateExtIO(). 

Delete the message port created by CreatePort(). 


Who Runs The Mouse? When the input device or Intution is operating, unit 0 is usually 
dedicated to gathering mouse events. The input device uses the gameport device to read 
the mouse events. (For applications that take over the machine without starting up the 
input device or Intuition, unit 0 can perform the same functions as unit 1.) See the “Input 
Device” chapter for more information on the input device. 


88 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The gameport device operates like the other Amiga devices. To use it, you must first open the 
gameport device, then send I/O requests to it, and then close it when finished. See the “Introduction 
to Amiga System Devices” chapter for general information on device usage. 


The I/O request used by the gameport device is called IOStdReq. 


struct IO0StdReq 
{ 


struct Message io Message; 


struct Device *io Device; /* device node pointer */ 

struct Unit *io Unit; /* unit (driver private) */ 

UWORD io_Command; /* device command */ 

UBYTE io Flags; 

BYTE io_Error; /* error or warning num */ 

ULONG io Actual; /* actual number of bytes transferred */ 
ULONG io_Length; /* requested number bytes transferred*/ 
APTR io_Data; /* points to data area */ 

ULONG io Offset; /* offset for block structured devices */ 


he 


See the include file exec/io.h for the complete structure definition. 


OPENING THE GAMEPORT DEVICE 


Three primary steps are required to open the gameport device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an I/O request structure of type IOStdReq. The IOStdReq structure is created by the 
CreateExtIO() function. CreateExtIOQ) will initialize the I/O request with your reply port. 


e Open the gameport device. Call OpenDevice(), passing the I/O request and and indicating the 
unit you wish to use. 


struct MsgPort *GameMP; /* Message port pointer */ 
struct I0StdReq *GameIO; /* I/O request pointer */ 


/* Create port for gameport device communications */ 
if (!(GameMP = CreatePort ("RKM_game_port",0))) 
cleanexit(" Error: Can’t create port\n",RETURN_FAIL); 


/* Create message block for device I/O */ 
if (!(GameIO = CreateExtIO(GameMP, sizeof (struct IOStdReq) ))) 
cleanexit (" Error: Can’t create I/O request\n",RETURN FAIL); 


/* Open the right/back (unit 1, number 2) gameport.device unit */ 


if (error=OpenDevice ("gameport.device",1,GameI0O, 0) ) 
cleanexit (" Error: Can’t open gameport.device\n", RETURN FAIL); 


The gameport commands are unit specific. The unit number specified in the call to OpenDevice() 
determines which unit is acted upon. 


Gameport Device 89 


GAMEPORT DEVICE CONTROLLERS 


The Amiga has five gameport device controller types. 


Gameport Device Controllers 


Controer Ty 


GPCT_MOUSE Mouse controller 


GPCT_ABSJOYSTICK Absolute (digital) joystick 
GPCT_RELJOYSTICK Relative (digital) joystick 
GPCT_ALLOCATED Custom controller 
GPCT_NOCONTROLLER No controller 





To use the gameport device, you must define the type of device connected to the gameport and 
define how the device is to respond. The gameport device can be set up to return the controller 
status immediately or only when certain conditions have been met. 


When a gameport device unit reponds to a request for input, it creates an input event. The contents 
of the input event will vary based on the type of device and the trigger conditions you have declared. 


e A mouse controller can report input events for one, two, or three buttons and for positive or 
negative (x,y) movements. A trackball controller or car-driving controller is generally of the 
same type and can be declared as a mouse controller. 


e An absolute joystick reports one single event for each change of its current location. If, for 


example, the joystick is centered and the user pushes the stick forward and holds it in that 
position, only one single forward-switch event will be generated. 


A relative joystick, on the other hand, is comparable to an absolute joystick with "autorepeat" 
installed. As long as the user holds the stick in a position other than centered, the gameport 
device continues to generate position reports. 


There is currently no system software support for proportional joysticks or proportional con- 
trollers (e.g., paddles). If you write custom code to read proportional controllers or other 
controllers (e.g., light pen) make certain that you issue GPD_SETCTYPE (explained below) 
with controller type GPCT_ALLOCATED to insure that other applications know the connector 
is being used. 


GPCT_NOCONTROLLER. The controller type GPCT_.NOCONTROLLER is not a 
controller at all, but a flag to indicate that the unit is not being used at the present time. 


CLOSING THE GAMEPORT DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIO() and remove them with WaitIO(. 


if (! (CheckIO(GameI0O) )) 
AbortIO(GameIO); /* Ask device to abort request, if pending */ 
} 


WaitIO((GameI0O) ; /* Wait for abort, then clean up */ 
CloseDevice (GameIO) ; 


90 Amiga ROM Kernel Reference Manual: Devices 


Gameport Events 


A gameport event is an InputEvent structure which describes the following: 
e The class of the event - always set to IECLASS_RAWMOUSE for the gameport device. 
e The subclass of the event - 0 for the left port; 1 for the right port. 
e The code - which button and its state. (No report = OxFF) 
e The qualifier - only button and relative mouse bits are set. 
e The position - either a data address or mouse position count. 
e The time stamp - delta time since last report, returned as frame count in tv_secs field. 
e The next event - pointer to next event. 


struct InputEvent GameEV 
{ 
struct InputEvent *ie NextEvent; /* next event */ 
UBYTE ie Class; * input event class */ 


UBYTE ie SubClass; /* subclass of the class */ 
UWORD ie Code; /* input event code */ 
UWORD ie Qualifier; /* event qualifiers in effect */ 
union 
{ 
struct 
{ 
WORD ie x; /* x position for the event */ 
WORD ie_y; /* y position for the event */ 
} ie_xy; 


APTR ie addr; 
} ie_position; 
struct timeval ie TimeStamp; /* delta time since last report 


See the include file devices/inputevent.h for the complete structure definition and listing of input 
event fields. ‘endverbatim 


READING GAMEPORT EVENTS 


You read gameport events by passing an I/O request to the device with GPD_READEVENT set in 
io_Comman4d, the address of the InputEvent structure to store events set in io_Data and the size 
of the structure set in io_Length. 


struct InputEvent GameEV; 
struct IO0StdRequest *GameIO; /* Must be initialized prior to using */ 


void send_read_request () 


GameIO->io_Command = GPD_READEVENT; /* Read events */ 
GameIO->io_Length = sizeof (struct InputEvent) ; 

GameIO->io Data = (APTR) &GameEV; /* put events in GameEV*/ 
SendIO(GameIO) ; /* Asynchronous */ 

} 


Gameport Device 91 


SETTING GAMEPORT EVENT TRIGGER CONDITIONS 


You set the conditions that can trigger a gameport event by passing an I/O request to the device with 
GPD_SETTRIGGER set in io_Command and the address of a GamePortTrigger structure set in 
io_Data. 


The information needed for gameport trigger setting is placed into a GamePortTrigger data struc- 
ture which is defined in the include file devices/gameport.h. 


struct GamePortTrigger 


{ 


UWORD gpt_Keys; /* key transition triggers */ 

UWORD gpt_Timeout; /* time trigger (vertical blank units) */ 
UWORD gpt_XDelta; /* X distance trigger */ 

UWORD gpt_YDelta; /* Y distance trigger */ 


} 


A few points to keep in mind with the GPD_SETTRIGGER command are: 


e Setting GPTF_UPKEYS enables the reporting of upward transitions. Setting 
GPTF_DOWNKEYS enables the reporting of downward transitions. These flags may both 
be specified. 


The field gpt_Timeout specifies the time interval (in vertical blank units) between reports in the 
absence of another trigger condition. In other words, an event is generated every gpt_Timeout 
ticks. Vertical blank units may differ from country to country (e.g 60 Hz NTSC, 50 Hz PAL.) 
To find out the exact frequency use this code fragment: 


#include <exec/execbase.h> 
extern struct ExecBase *SysBase; 


UBYTE get_frequency (void) 


{ 
return ( (UBYTE) SysBase->VBlankFrequency) ; 
} 


e The gpt_XDelta and gpt_YDelta fields specify the x and y distances which, if exceeded, 
trigger a report. 


For a mouse controller, you can trigger on a certain minimum-sized move in either the x or y 
direction, on up or down transitions of the mouse buttons, on a timed basis, or any combination of 
these conditions. 


For example, suppose you normally signal mouse events if the mouse moves at least 10 counts in 
either the x or y directions. If you are moving the cursor to keep up with mouse movements and 
the user moves the mouse less than 10 counts, after a period of time you will want to update the 
position of the cursor to exactly match the mouse position. Thus the timed report of current mouse 
counts would be preferred. The following structure would be used: 


#define XMOVE 10 
#define YMOVE 10 


struct GamePortTrigger GameTR = 
{ 
GPTF_UPKEYS | GPTF_DOWNKEYS, /* trigger on all key transitions */ 
00, /* and every 36(PAL) or 30(NTSC) seconds */ 


XMOVE, /* for any 10 in an x or y direction */ 
YMOVE 


92 Amiga ROM Kernel Reference Manual: Devices 


For a joystick controller, you can select timed reports as well as button-up and button-down report 
trigger conditions. For an absolute joystick specify a value of one (1) for the GameTR_XDelta 
and GameTR_YDelta fields or you will not get any direction events. You set the trigger conditions 
by using the following code or its equivalent: 


struct IOStdReq *GameI0O; 


void set_trigger_ conditions(struct GamePortTrigger *GameTR) 

{ 

GameIO->io Command = GPD_SETTRIGGER; /* set trigger conditions */ 
GameIO->io Data = (APTR)GameTR; /* from GameTR */ 
GameIO->io Length = sizeof (struct GamePortTrigger) ; 

Do1IO(GameI0O) ; 

} 


Triggers and Reads. If a task sets trigger conditions and does not ask for the position 
reports the gameport device will queue them up anyway. If the trigger conditions occur 
again and the gameport device buffer is filled, the additional triggers will be ignored until the 
buffer is read by a device read request (GPD_READEVENT) or a system CMD_CLEAR 
command flushes the buffer. 


DETERMINING THE TRIGGER CONDITIONS 


You determine the conditions required for triggering gameport events by passing an I/O request to 
the device with GPD_ASKTRIGGER set in io_Comman4d, the length of the GamePortTrigger 
structure set in io_Length and the address of the structure set in io_Data. The gameport device 
will respond with the event trigger conditions currently set. 

struct IO0StdReq *GameIO; /* Must be initialized prior to using */ 

struct GamePortTrigger GameTR; 

void get_trigger_conditions(struct GamePortTrigger *GameTR) 

{ 

GameI0O->io_ Command = GPD_ASKTRIGGER; /* get type of triggers */ 

GameIO->io Data = (APTR)GameTR; /* place data here */ 

GameIO->io Length= sizeof (GameTR) ; 


DoIO (GameI0O) ; 
} 


Gameport Device 93 


Setting and Reading the Controller Type 


DETERMINING THE CONTROLLER TYPE 


You determine the type of controller being used by passing an I/O request to the device with 
GPD_ASKCTYPE set in io_Command, 1 set in io_Length and the number of the unit set in 
io_Unit. The gameport device will respond with the type of controller being used. 


struct I0StdReq *GameIO; /* Must be initialized prior to using */ 
BYTE GetControllerType () 

{ 

BYTE controller type = 0; 


GameI0O->io_Command = GPD_ASKCTYPE; /* get type of controller */ 
Gamel0O->io Data = (APTR)&controller type; /* place data here */ 
GameI0O->io Length = 1; 

DoIlO (GameI0O) ; 

return (controller type); 

} 


The BYTE value retumed corresponds to one of the five controller types noted above. 


SETTING THE CONTROLLER TYPE 


You set the type of gameport controller by passing an I/O request to the device with 
GPD_SETCTYPE set in io_Command, 1 set in io_Length and the address of the byte variable 
describing the controller type set in io_Data. 


The gameport device is a shared device; many tasks may have it open at any given time. Hence, a 
high level protocol has been established to prevent multiple tasks from reading the same unit at the 
same time. 


Three Step Protocol for Using the Gameport Device 


Step 1: 
Send GPD_ASKCTYPE to the device and check for a GPCT_NOCONTROLLER retum. 
Never issue GPD_SETCTYPE without checking whether the desired gameport unit is in use. 


Step 2: 
If GPCT_.NOCONTROLLER is retumed, you have access to the gameport. Set the alloca- 
tion flag to GPCT_MOUSE, GPCT_ABSJOYSTICK or GPCT_RELJOYSTICK if you use a 
system supported controller, or GPCT_ALLOCATED if you use a custom controller. 


struct I0StdReq *GameIO; /* Must be initialized prior to using */ 


BOOL set_controller type (type) 
BYTE type; 
{ 


BOOL success = FALSE; 
BYTE controller type = 0; 


Forbid (); /*critical section start */ 
GameI0O->io_Command = GPD_ASKCTYPE; /* inquire current status */ 
GameIO->io Length = 1; 

GameI0->io Flags = IOF_QUICK; 

GameIO->io_ Data = (APTR)&controller type; /* put answer in here */ 


94 Amiga ROM Kernel Reference Manual: Devices 


DoIO (GameIO) ; 


/* No one is using this device unit, let’s claim it */ 
if (controller _type == GPCT_NOCONTROLLER) 


{ 

GameIO->io_Command = GPD_SETCTYPE;/* set controller type */ 
GameIO->io_Length = 1; 

GameIO->io Data = (APTR)&type; /* set to input param */ 


DoIO( GameI0O) ; 
success = TRUE; 
UnitOpened = TRUE; 


Permit (); /* critical section end */ 


/* success can be TRUE or FALSE, see above */ 
return (success); 


} 


Step 3: 
The program must set the controller type back to GPCT_.NOCONTROLLER upon exiting your 
program: 


struct IOStdReq *GameIO; /* Must be initialized prior to using */ 


void free_gp unit () 

{ 

BYTE type = GPCT_NOCONTROLLER; 

GameIO->io Command = GPD_SETCTYPE; /* set controller type */ 
GameIO->io_Length = 1; 

GameIO->io Data = (APTR) &type; /* set to unused */ 

DoIO( GameIO) ; 

} 


This three step protocol allows applications to share the gameport device in a system compatible 
way. 


A Word About The Functions. The functions shown above are designed to be included 
in any application using the gameport device. The first function, set_controller_typeQ, 
would be the first thing done after opening the gameport device. The second function, 
free_gp_unit(), would be the last thing done before closing the device. 


Joystick Example Program 


. Absolute _Joystick.c 

7 Gameport device absolute joystick example 

i Compile with SAS 5.10 lec -bl -cfistq -v -y -L 
ipo from CLI only 


#include <exec/types.h> 

#include <exec/io.h> 

#include <exec/memory.h> 
#include <intuition/intuition.h> 
#include <exec/exec.h> 

#include <dos/dos.h> 

#include <devices/gameport.h> 
#include <devices/inputevent.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/dos_ protos.h> 
#include <clib/intuition_protos.h> 


Gameport Device 95 


#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#endif 


#define JOY _X DELTA (1) 
#define JOY_Y DELTA (1) 
#define TIMEOUT SECONDS (10) 


extern struct ExecBase *SysBase; 


** Routine to print out some information for the user. 
*7 
VOID printInstructions (VOID) 


{ 
printf("\n >>> gameport.device Absolute Joystick Demo <<<\n\n"); 


if (SysBase->VBlankFrequency==60) 

printf(" Running on NTSC system (60 Hz).\n"); 
else if (SysBase->VBlankFrequency==50) 

printf(" Running on PAL system (50 Hz).\n"); 


printf( " Attach joystick to rear connector (A3000) and (A1000).\n" 
"Attach joystick to right connector (A2000).\n" 
"Attach joystick to left connector (A500) .\n" 
" Then move joystick and click its button(s).\n\n" 
" To exit program press and release fire button 3 consecutive times. \n" 
"The program also exits if no activity occurs for 1 minute.\n\n"); 


** print out information on the event received. 
* 


BOOL check_move(struct InputEvent *game_event) 


{ 


WORD xmove, ymove; 
BOOL timeout=FALSE; 


xmove = game_event->ie_X; 
ymove = game_event->ie_Y; 


if (xmove == 1) 
{ 
if (ymove == 1) printf("RIGHT DOWN\n"); 
else if (ymove == 0) printf ("RIGHT\n"); 
else if (ymove ==-1) printf ("RIGHT UP\n"); 
else printf ("UNKNOWN Y\n") ; 
} 

else if (xmove ==-1) 
{ 
if (ymove == 1) printf("LEFT DOWN\n"); 
else if (ymove == 0) printf ("LEFT\n"); 
else if (ymove ==-1) printf ("LEFT UP\n"); 
else printf ("UNKNOWN Y\n"); 
} 

else if (xmove == 0) 
{ 
if (ymove == 1) printf ("DOWN\n"); 
/* note that 0,0 can be a timeout, or a direction release. */ 
else if (ymove == 0) 


if (game_event->ie_TimeStamp.tv_secs >= 
(UWORD) (SysBase->VBlankFrequency) * TIMEOUT SECONDS) 
{ 


printf ("TIMEOUT\n") ; 
timeout=TRUE; 


} 
else printf ("RELEASE\n") ; 


else if (ymove ==-1) printf ("UP\n"); 
else printf ("UNKNOWN Y\n"); 
} 


96 Amiga ROM Kernel Reference Manual: Devices 


else 


{ 
printf ("UNKNOWN X "); 


if (ymove == 1) printf("unknown action\n"); 
else if (ymove == 0) printf("unknown action\n"); 
else if (ymove ==-1) printf ("unknown action\n"); 


else printf ("UNKNOWN Y\n"); 
} 


return (timeout) ; 


** send a request to the gameport to read an event. 

*/ 

VOID send_read_request( struct InputEvent *game_event, 
struct IOStdReq *game_io_ msg) 

{ 


game_io_msg->io_Command 
game_io_msg->io Flags 
game_io_msg->io Data 
game_io_msg->io_Length 
SendIO(game_io_msg); /* 
} 


GPD_READEVENT; 


(APTR) game_event; 
sizeof (struct InputEvent) ; 
synchronous - message will return later */ 


pion i 


**x simple loop to process gameport events. 

*/ 

VOID procesSsEvents( struct IOStdReq *game_io msg, 
struct MsgPort *game_msg port) 


{ 

BOOL timeout; 

SHORT timeouts; 

SHORT button_count; 

BOOL not_finished; 

struct InputEvent game_event; /* where input event will be stored */ 


/* From now on, just read input events into the event buffer, 
** one at a time. READEVENT waits for the preset conditions. 
*/ 

timeouts = 0; 
button_count 
not_finished 


0; 
TRUE; 


while ((timeouts < 6) && (not_finished) ) 


{ 
/* Send the read request */ 
send_read_request (&game_event, game_io_msg); 


/* Wait for joystick action */ 
Wait (1L << game_msg_port->mp_SigBit); 
while (NULL != GetMsg(game_msg_port) ) 


{ 
timeout=FALSE; 
switch (game_event.ie Code) 
{ 
case IECODE LBUTTON: 
printf (" FIRE BUTTON PRESSED \n"); 
break; 


case (IECODE_LBUTTON | IECODE_UP PREFIX): 
printf(" FIRE BUTTON RELEASED \n"); 


if (3 == ++button_count) 
not_finished = FALSE; 
break; 


case IECODE_RBUTTON: 
printf(" ALT BUTTON PRESSED \n"); 
button _count = 0; 
break; 


case (IECODE_RBUTTON | IECODE_UP_ PREFIX): 
printf(" ALT BUTTON RELEASED \n"); 
button_count = 0; 
break; 


Gameport Device 97 


case IECODE NOBUTTON: 
/* Check for change in position */ 
timeout = check_move (&game_event) ; 
button_count = 0; 
break; 


default: 
break; 
} 


if (timeout) 
timeoutstt+; 

else 
timeouts=0; 


** allocate the controller if it is available. 

** you allocate the controller by setting its type to something 
** other than GPCT NOCONTROLLER. Before you allocate the thing 
** you need to check if anyone else is using it (it is free if 
** it is set to GPCT NOCONTROLLER) . 

*/ 

BOOL set_controller type (BYTE type, struct IOStdReq *game_io_msg) 
{ 


BOOL success = FALSE; 
BYTE controller type = 0; 


/* begin critical section 

** we need to be sure that between the time we check that the controller 
** is available and the time we allocate it, no one else steals it. 

*/ 

Forbid (); 


game_io_msg->io_Command 
game_io_msg->io_ Flags 
game_io_msg->io_Data 
game_io_msg->io_Length 
DoIO(game_io_msg); 


GPD_ASKCTYPE; /* inquire current status */ 
IOF_QUICK; 

(APTR) &controller type; /* put answer in here */ 
1; 


iow 


/* No one is using this device unit, let’s claim it */ 

if (controller type == GPCT_NOCONTROLLER) 
{ 
game_io_msg->io_Command 
game_io_msg->io Flags 
game_io_msg->io Data 
game_io msg->io_ Length 
DoIO( game_io_msg); 
success = TRUE; 


} 


Permit(); /* critical section end */ 
return (success) ; 


GPD_SETCTYPE; 
IOF_QUICK; 
(APTR) &type; 
1; 


** tell the gameport when to trigger. 

x/ 

VOID set_trigger_conditions(struct GamePortTrigger *gpt, 
struct IOStdReq *game_io_msg) 

{ 


/* trigger on all joystick key transitions */ 

gpt->gpt_Keys GPTF_UPKEYS | GPTF_DOWNKEYS; 

gpt->gpt_XDelta JOY_X_ DELTA; 

gpt->gpt_YDelta JOY_Y DELTA; 

/* timeout trigger every TIMEOUT _SECONDS second(s) */ 

gpt->gpt_Timeout = (UWORD) (SysBase->VBlankFrequency) * TIMEOUT SECONDS; 


game_io_msg->io_Command 
game_io_msg->io_Flags 
game_io_msg->io_ Data 
game _io msg->io Length 
DolO(game_io_ msg); 


} 


GPD_SETTRIGGER; 

IOF_QUICK; 

(APTR) gpt; 

(LONG) sizeof (struct GamePortTrigger) ; 


98 Amiga ROM Kernel Reference Manual: Devices 


** clear the buffer. do this before you begin to be sure you 
** start in a known state. 

*/ 

VOID flush_buffer(struct IOStdReq *game_io_msg) 

{ 


game_io_msg->io_Command be 
game_io_ msg->io Flags IOF_QUICK; 
game_io_msg->io Data NULL; 
game_io_msg->io_ Length ; 
DoI0(game_io_ msg); 


CMD_CLEAR; 


** free the unit by setting its type back to GPCT_NOCONTROLLER. 
*/ 

VOID free_gp_unit (struct I0StdReq *game_io_ msg) 

{ 

BYTE type = GPCT_NOCONTROLLER; 


game_io_msg->io_ Command 
game_ io_msg->io | Flags 
game_io_msg->io Data 
game_io_msg->io Length 
DoI0(game_io msg); 


GPD_SETCTYPE; 
IOF_QUICK; 
(APTR) &type; 
1; 


** allocate everything and go. On failure, free any resources that 

** have been allocated. this program fails quietly--no error messages. 
*/ 

VOID main(int argc,char **argv) 


struct GamePortTrigger joytrigger; 
struct IOStdReq *game_io_msg; 
struct MsgPort *game_msg_ port; 


/* Create port for gameport device communications */ 
if (game_msg_port = CreatePort ("RKM_game_port",0)) 
{ 


/* Create message block for device IO */ 
if (game_io_msg = (struct IOStdReq *) 
CreateExtI0(game_msg_port, sizeof (*game_io_msg))) 
{ 
game_io_msg->io_Message.mn_Node.1n Type = NT_UNKNOWN; 
/* Open the right/back (unit 1, number 2) gameport.device unit */ 
if (!OpenDevice ("gameport.device",1,game_io_msg,0)) 
{ 
/* Set controller type to joystick */ 
if (set_controller_type(GPCT_ABSJOYSTICK, game_io_msg) ) 
{ 


/* Specify the trigger conditions */ 
set_trigger conditions (&joytrigger,game_io_msg); 


printInstructions(); 

/* Clear device buffer to start from a known state. 
a There might still be events left 
flush_buffer(game_io_msg) ; 

processEvents (game_io_msg,game_msg_port); 


/* Free gameport unit so other applications can use it ! */ 
free gp unit (game_io_msg); 


CloseDevice (game_io_msg); 
} 
DeleteExt10(game_io_msg); 
} 


DeletePort (game_msg_port); 
} 


Gameport Device 99 


Additional Information on the Gameport Device 


Additional programming information on the gameport device can be found in the include files and 
the Autodocs for the gameport and input devices. Both are contained in the Amiga ROM Kernel 
Reference Manual: Includes and Autodocs. 


Gameport Device Information 


INCLUDES devices/gameport.h 
devices/gameport.i 


devices/inputevent.h 
devices/inputevent.i 


AUTODOCS gameport.doc 





100 Amiga ROM Kernel Reference Manual: Devices 


chapter six 
INPUT DEVICE 


The input device is the central collection point for input events disseminated throughout the system. 
The best way to describe the input device is a manager of a stream with feeders. The input device 
itself and other modules such as the file system add events to the stream; so do input device 
“users”—programs or other devices that use parts of the stream or change it in some way. Feeders 
of the input device include the keyboard, timer and gameport devices. The keyboard, gameport, 
and timer devices are special cases in that the input device opens them and asks them for input. 
Users of the input device include Intuition and the console device. 


New Features for Version 2.0 
Feature Description 


IECLASS_NEWPOINTERPOS Input Event Class 
IECLASS_MENUHELP Input Event Class 


IECLASS_CHANGEWINDOW Input Event Class 
IESUBCLASS_COMPATIBLE Input Event SubClass 
IESUBCLASS_PIXEL Input Event SubClass 
IESUBCLASS_TABLET Input Event SubClass 
PeekQualifierQ Function 





Compatibility Warning: The new features for the 2.0 input device are not backwards 
compatible. 


Input Device 101 


Input Device Commands and Functions 


Command 


CMD_FLUSH 
CMD_RESET 


CMD_START 
CMD_STOP 


IND_ADDHANDLER 
IND_REMHANDLER 
IND_SETMPORT 
IND_SETMTRIG 


IND_SETMTYPE 
IND_SETPERIOD 
IND_SETTHRESH 
IND_WRITEEVENT 


input Device Function 


PeekQualifier() 


Operation 


Purge all active and queued requests for the input device. 

Reset the input port to its initialized state. All active and queued I/O 
requests will be aborted. Restarts the device if it has been stopped. 
Restart the currently active input (if any) and resume queued I/O 
requests. 

Stop any currently active input and prevent queued I/O requests from 
Starting. 

Add an input-stream handler into the handler chain. 

Remove an input-stream handler from the handler chain. 

Set the controller port to which the mouse is connected. 

Set conditions that must be met by a mouse before a pending read 
request will be satisfied. 

Set the type of device at the mouse port. 

Set the period at which a repeating key repeats. 

Set the repeating key hold-down time before repeat starts. 
Propagate an input event stream to all devices. 


Return the input device’s current qualifiers. (V36) 


Exec Functions as Used In This Chapter 


AbortIOQ) 
CheckIOQ 
CloseDevice() 
DoIOO 
OpenDevice() 
SendIOQ( 


Abort a command to the input device. 

Retum the status of an I/O request. 

Relinquish use of the input device. 

Initiate a command and wait for completion (synchronous request). 
Obtain shared use of the input device. 

Initiate a command and return immediately (asynchronous request). 


Exec Support Functions as Used in This Chapter 


CreateExtIO() 
CreatePort() 


DeleteExtIO() 
DeletePort() 


Create an extended I/O request structure of type IOStdReq. This 
structure will be used to communicate commands to the input device. 
Create a signal message port for reply messages from the input device. 
Exec will signal a task when a message arrives at the reply port. 
Delete an I/O request structure created by CreateExtIO(). 

Delete the message port created by CreatePort(). 


102 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The input device operates like the other Amiga devices. To use it, you must first open the input 
device, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
System Devices” chapter for general information on device usage. 


A number of structures are used by the input device to do its processing. Some are used to pass 
commands and data to the device, some are used to describe input events like mouse movements 
and key depressions, and one structure is used to describe the environment for input event handlers. 


The I/O request used by the input device for most commands is IOStdReq. 


struct I0StdReq 
{ 


struct Message io Message; /* message reply port */ 
struct Device *io Device; /* device node pointer */ 
* 


struct Unit *io Unit; /* unit */ 

UWORD io Command; /* input device command */ 

UBYTE io Flags; /* input device flags */ 

BYTE io_Error; /* error code */ 

ULONG io Length; /* number of bytes to transfer */ 
APTR io_ Data; /* pointer to data area */ 


he 


See the include file exec/io.h for the complete structure definition. 


Two of the input device commands—IND_SETTHRESH and IND_SETPERIOD—require a time 
specification and must use a timerequest structure instead of an IOStdReq. 

struct timerequest 

struct IORequest tr_node; 


struct timeval tr_time; 


}e 


As you can see, the timerequest structure includes an IORequest structure. The io_Command 
field of theIORequest indicates the command to the input device and the timeval structure sets the 
time values. See the include file devices/timer.h for the complete structure definition. 


In Case You Feel Like Reinventing the Wheel... You could define a “super- 
IORequest” structure for the input device which would combine the IOStdReq fields 
with the timeval structure of the timerequest structure. 


OPENING THE INPUT DEVICE 


Three primary steps are required to open the input device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an I/O request structure of type [OStdReq or timerequest. The I/O request created by 
the CreateExtIO() function will be used to pass commands and data to the input device. 


e Open the Input device. Call OpenDevice(), passing the I/O request. 


Input Device 103 


struct MsgPort *InputMP; /* Message port pointer */ 
struct IOStdReq *InputI0O; /* I/O request pointer */ 


if (InputMP=CreatePort (0,0) ) 
if (InputIO=(struct I0StdReq *) 
CreateExtIO(InputMP, sizeof (struct IO0StdReq)) ) 
if (OpenDevice ("input.device", OL, (struct IORequest *)InputIO,0) ) 
printf ("input.device did not open\n"); 


The above code will work for all the input device commands except for the ones which require a 
time specification. For those, the code would look like this: 


#include <devices/timer.h> 


struct MsgPort *InputMP; /* Message port pointer */ 
struct timerequest *InputI0O; /* I/O request pointer */ 


if (InputMP=CreatePort (0,0) ) 
if (InputIO=(struct timerequest *) 
CreateExtIO(InputMP, sizeof (struct timerequest)) ) 
if (OpenDevice ("input.device", OL, (struct IORequest *)InputI0O,0) ) 
printf ("input.device did not open\n"); 


INPUT DEVICE EVENT TYPES 


The input device is automatically opened by the console device when the system boots. When the 
input device is opened, a task named “‘input.device”’ is started. The input device task communicates 
directly with the keyboard device to obtain raw key events. It also communicates with the gameport 
device to obtain mouse button and mouse movement events and with the timer device to obtain time 
events. In addition to these events, you can add your own input events to the input device, to be fed 
to the handler chain (see below). 


The keyboard device is accessible directly (see the “Keyboard Device” chapter). However, once the 
input.device task has started, you should not read events from the keyboard device directly, since 
doing so will deprive the input device of the events and confuse key repeating. 


The gameport device has two units. As you view the Amiga, looking at the gameport connectors, 
the left connector is assigned as the primary mouse input for Intuition and contributes gameport 
input events to the input event stream. 


The right connector is handled by the other gameport unit and is currently unassigned. While the 
input device task is running, that task expects to read the input from the left connector. Direct use 
of the gameport device is covered in the “Gameport Device” chapter of this manual. 


The timer device is used to generate time events for the input device. It is also used to control key 
repeat rate and key repeat threshold. The timer device is a shared-access device and is described in 
“Timer Device” chapter of this manual. 


The device-specific commands are described below. First though, it may be helpful to consider 
the types of input events that the input device deals with. An input event is a data structure that 
describes the following: 


e The class of the event — often describes the device that generated the event. 
e The subclass of the event — space for more information if needed. 

e The code — keycode if keyboard, button information if mouse, others. 

e A qualifier such as “Alt key also down,”or “key repeat active”. 


104 Amiga ROM Kernel Reference Manual: Devices 


e A position field that contains a data address or a mouse position count. 


e A time stamp, to determine the sequence in which the events occurred. 
e A link-field by which input events are linked together. 
e The class, subclass, code and qualifier of the previous down key. 


The full definitions for each field can be found in the include file devices/inputevent.h. You can find 
more information about input events in the “Gameport Device” and “Console Device” chapters of 


this manual. 


The various types of input events are listed below. 


Input Device Event Types 


IECLASS_NULL 
IECLASS_RAWKEY 
IECLASS_RAWMOUSE 
IECLASS_EVENT 
IECLASS_POINTERPOS 
IECLASS_TIMER 
IECLASS_GADGETDOWN 


IECLASS_GADGETUP 


IECLASS_REQUESTER 
IECLASS_MENULIST 


IECLASS_CLOSEWINDOW 
IECLASS_SIZEWINDOW 
IECLASS_REFRESH WINDOW 


IECLASS_NEWPREFS 
IECLASS_DISKREMOVED 
IECLASS_DISKINSERTED 
IECLASS_ACTIVEWINDOW 
IECLASS_INACTIVEWINDOW 
IECLASS_NEWPOINTERPOS 
IECLASS_MENUHELP 
IECLASS_CHANGEWINDOW 


A NOP input event 

A raw keycode from the keyboard device 

The raw mouse report from the gameport device 

A private console event 

A pointer position report 

A timer event 

Select button pressed down over a gadget (address in 
ie_EventAddress) 

Select button released over the same gadget (address 
in ie_EventAddress) 

Some requester activity has taken place. 

This is a menu number transmission (menu number is 
in ie_Code) 

User has selected the active window’s Close Gadget 
This window has a new size 

The window pointed to by ie_EventAddress needs to 
be refreshed 

New preferences are available 

The disk has been removed 

The disk has been inserted 

The window is about to be been made active 

The window is about to be made inactive 
Extended-function pointer position report (V36) 

Help key report during Menu session (V36) 

The Window has been modified with move, size, zoom, 
or change (V36) 


There is a difference between simply receiving an input event from a device and actually becoming 
a handler of an input event stream. A handler is a routine that is passed an input event list. It is 
up to the handler to decide if it can process the input events. If the handler does not recognize an 
event, it leaves it undisturbed in the event list. 


It All Flows Downhill. Handlers can themselves generate new linked lists of events 
which can be passed down to lower priority handlers. 


Input Device 105 


The InputEvent structure is used by the input device to describe an input event such as a keypress 
or a mouse movement. 


struct InputEvent 
{ 


struct InputEvent *ie NextEvent; /* the chronologically next event */ 
UBYTE ie Class; = /* the input event class */ 
UBYTE ie SubClass; /* optional subclass of the class */ 
UWORD ie Code; /* the input event code */ 
UWORD ie Qualifier; /* qualifiers in effect for the event*/ 
union 
{ 
struct 
WORD ie_x; /* the pointer position for the event*/ 
WORD je_y; 
} ie_xy; 
APTR ie_addr; /* the event address */ 
struct 
{ 
UBYTE ie_prev1lDownCode; /* previous down keys for dead */ 
UBYTE ie_prev1lDownQual; /* key translation: the ie Code */ 
UBYTE ie_prev2DownCode; /* & low byte of ie Qualifier for */ 
UBYTE ie_prev2DownQual; /* last & second last down keys */ 
} ie_dead; 
} ie_position; 
struct timeval ie TimeStamp; /* the system tick at the event */ 


The IEPointerPixel and IEPointerTablet structures are used to set the mouse position with the 


IECLASS_NEWPOINTERPOS input event class. 


struct IEPointerPixel 


struct Screen *iepp Screen; /* pointer to an open screen */ 


struct 

{ /* pixel coordinates in iepp Screen */ 
WORD X; 
WORD Y; 


} iepp_Position; 


Me 
struct IEPointerTablet 
{ 


struct 
{ 
UWORD X; 
UWORD Y; 
} iept_Range; /* 0 is min, these are max */ 
struct 
UWORD X; 
UWORD Y; 
} iept_Value; /* between 0 and iept_ Range */ 


WORD iept Pressure; /* -128 to 127 (unused, set to 0) */ 
Me 


See the include file devices/inputevent.h for the complete structure definitions. 


For input device handler installation, the Interrupt structure is used. 


struct Interrupt 

{ 
struct Node is Node; 
APTR is Data; 


Ey /* server data segment */ 
VOID (*is Code) (); 


/* server code entry */ 


}; 


See the include file exec/interrupts.h for the complete structure definition. 


106 Amiga ROM Kernel Reference Manual: Devices 


CLOSING THE INPUT DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). All I/O requests must 
be complete before CloseDevice(). If any requests are still pending, abort them with AbortIOQ: 


if (! (CheckIO(InputI0O) )) 
{ 
AbortIO(InputIO); /* Ask device to abort request, if pending */ 
} 


WaitIO(InputI0); /* Wait for abort, then clean up */ 
CloseDevice((struct IORequest *)InputIO); 


Using the Mouse Port With the Input Device 


To get mouse port information you must first set the current mouse port by passing an IOStdReq 
to the device with IND_SETMPORT set in io_Command and a pointer to a byte set in io_Data. If 
the byte is set to 0 the left controller port will be used as the current mouse port; if it is set to 1, the 
right controller port will be used. 


BYTE port = 1; /* set mouse port to right controller */ 


InputIO->io_Data = &port; 
InputI0O->io Flags = IOF_QUICK; 
InputIO->io Length = 1; 


InputIO->io Command = IND_SETMPORT; 
BeginIO((struct IORequest *) InputIO); 
if (InputIO->io_Error) 
printf ("\nSETMPORT failed %d\n",InputI0O->io Error); 


Put That Back! The default mouse port is the left controller. Don’t forget to set the 
mouse port back to the left controller before exiting if you change it to the right controller 
during your application. 


SETTING THE CONDITIONS FOR A MOUSE PORT REPORT 


You set the conditions for a mouse port report by passing an IOStdReq to the device with 
IND_SETMTRIG set in io_Command, the address of aGamePortTrigger structure set in io_Data 
and the length of the structure set in io_Length. 

struct GamePortTrigger InputTR; 

InputIO->io Data = (APTR) InputTR; /* set trigger conditions */ 

InputIO->io Command = IND SETMTRIG; /* from InputTR */ 


InputIO->io Length = sizeof(struct GamePortTrigger) ; 
DoIO(InputI0O) ; 


The information needed for mouse port report setting is contained in a GamePortTrigger data 
structure which is defined in the include file devices/gameport.h. 


struct GamePortTrigger 


UWORD gpt_Keys; /* key transition triggers */ 

UWORD gpt_Timeout; /* time trigger (vertical blank units) */ 
UWORD gpt_XDelta; /* X distance trigger */ 

UWORD gpt_YDelta; /* Y distance trigger */ 


F 


See the ““Gameport Device” chapter of this manual for a full description of setting mouse port trigger 
conditions. 


Input Device 107 


Adding an Input Handler 


You add an input-stream handler to the input chain by passing an IOStdReq to the device with 
IND_ADDHANDLER set in io_Command and a pointer to an Interrupt structure set in io_Data. 


struct Interrupt *InputHandler; 
struct I0StdReq *InputIO 


InputHandler->is_ Code=ButtonSwap; /* Address of code */ 
InputHandler->is Data=NULL; /* User Value passed in Al */ 
InputHandler->is Node.1n Pri=100; /* Priority in food chain */ 
InputHandler->is Node.1ln Name=NameString; /* Name of handler */ 

Input IO->io_Data=(APTR) inputHandler; /* Point to the structure */ 
Input I0O->io_Command=IND_ADDHANDLER; /* Set command ... * 
DoIO((struct IORequest *)InputI0O); /* DoIO( ) the command */ 


Intuition is one of the input device handlers and normally distributes most of the input events. 


Intuition inserts itself at priority position 50. The console device sits at priority position 0. You can 
choose the position in the chain at which your handler will be inserted by setting the priority field 
in the list-node part of the interrupt data structure you pass to this routine. 


Speed Saves. Any processing time expended by a handler subtracts from the time 
available before the next event happens. Therefore, handlers for the input stream must be 
fast. For this reason it is recommended that the handlers be written in assembly. 


RULES FOR INPUT DEVICE HANDLERS 


The following rules should be followed when you are designing an input handler: 


e If an input handler is capable of processing a specific kind of an input event and that event has 
no links (ie_NextEvent = 0), the handler can end the handler chain by retuming a NULL (0) 
value. 


e 


If there are multiple events linked together, the handler is free to unlink an event from the 
input event chain, thereby passing a shorter list of events to subsequent handlers. The starting 
address of the modified list is the return value. 


e If a handler wishes to add new events to the chain that it passes to a lower-priority handler, it 
may initialize memory to contain the new event or event chain. The handler, when it again gets 
control on the next round of event handling, should assume nothing about the current contents 
of the memory blocks attached to the event chain. Lower priority handlers may have modified 
the memory as they handled their part of the event. The handler that allocates the memory for 
this purpose should keep track of the starting address and the size of this memory chunk so that 
the memory can be retumed to the free memory list when it is no longer needed. 


Your assembly language handler routine should be structured similar to the following pseudo- 
language statement: 


newEventChain = yourHandlerCode(oldEventChain, yourHandlerData) ; 
do = a0 al 


108 Amiga ROM Kernel Reference Manual: Devices 


where: 
e yourHandlerCode is the entry point to your routine. 
e oldEventChain is the starting address for the current chain of input events. 


e yourHandlerData is a user-definable value, usually a pointer to some data structure your 
handler requires. 


e newEventChain is the starting address of an event chain which you are passing to the next 
handler, if any. 


When your handler code is called, the event chain is passed in AO and the handler data is passed 
in Al. (You may choose not to use Al.) When your code retums, it should retum the pointer to 
the event chain in DO. If all of the events were removed by the routine, retum NULL. A NULL (0) 
value terminates the handling thus freeing more CPU resources. 


Memory that you use to describe a new input event that you have added to the event chain is available 
for reuse or deallocation when the handler is called again or after the IND-REMHANDLER 
command for the handler is complete. There is no guarantee that any field in the event is unchanged 
since a handler may change any field of an event that comes through the food chain. 


Do Not Confuse the Device. Altering a repeat key report will confuse the input device 
when it tries to stop the repeating after the key is raised under pre-V36 Kickstart. 


Because IND-ADDHANDLER installs a handler in any position in the handler chain, it can, for 
example, ignore specific types of input events as well as act upon and modify existing streams of 
input. It can even create new input events for Intuition or other programs to interpret. 


REMOVING AN INPUT HANDLER 


You remove a handler from the handler chain by passing an IOStdReq to the device 
IND_REMHANDLER set in io_Command and a pointer to the Interrupt structure used to add 
the handler. 


struct Interrupt *InputHandler; 
struct IO0StdReq *InputI0O; 


InputIO->io_ Data=(APTR) InputHandler; /* Which handler to REM */ 


Input IO->io _Command=IND_REMHANDLER; /* The REM command */ 
DoIO((struct IORequest *)InputIO); /* Send the command */ 


Writing Events to the Input Device Stream 


Typically, input events are internally generated by the timer device, keyboard device, and input 
device. 


An application can also generate an input event by setting the appropriate fields for the event in 
an InputEvent structure and sending it to the input device. It will then be treated as any other 
event and passed through to the input handler chain. However, I/O requests for IND_WRITEVENT 
cannot be made from interrupt code. 


You generate an input event by passing an IOStdReq to the device with IND_WRITEEVENT set 
in io_Comman4d, a pointer to an InputEvent structure set in io_Data and the length of the structure 
set in io_Length. 


Input Device 109 


struct InputEvent *FakeEvent; 
struct I0StdReq *InputI0; 


InputIO->io_Data=(APTR) FakeEvent; 
InputI0->io Length=sizeof (struct InputEvent) ; 


Input I0O->io_Command=IND_WRITEEVENT; 
DoIO((struct IORequest *)InputIO); 


You Know What Happens When You Assume. This command propagates the input 
event through the handler chain. The handlers may link other events onto the end of this 
event or modify the contents of the data structure you constructed in any way they wish. 
Therefore, do not assume any of the data will be the same from event to event. 


SETTING THE POSITION OF THE MOUSE 


One use of writing input events to the input device is to set the position of the mouse pointer. 
The mouse pointer can be positioned by using the input classes IECLASS_POINTERPOS and 
IECLASS_NEWPOINTERPOS. 


There are two ways to set the position of the mouse pointer using the pre-V36 Kickstart input class 
IECLASS_POINTERPOS: 


e At an absolute position on the current screen. 


e Ata position relative to the current mouse pointer position on the current screen. 


In both cases, you set the Class field of the InputEvent structure to IECLASS_POINTERPOS, 
ie_X with the new x-coordinate and ie_Y with the new y-coordinate. Absolute positioning is 
done by setting ie_Qualifier to NULL and relative positioning is done by setting ie_Qualifier to 
RELATIVE_MOUSE. 


Once the proper values are set, pass an IOStdReq to the input device with a pointer to the 
InputEvent structure set in io_Data and io_Command set to IND-WRITEEVENT. 


There are three ways to set the mouse pointer position using IECLASS_NEWPOINTERPOS: 


e At an absolute x-y coordinate on a screen—you specify the exact location of the pointer and 
which screen. 


e At an relative x-y coordinate—you specify where it will go in relation to the current pointer 
position and which screen. 


e Ata normalized position on a tablet device—you specify the maximum x-value and y-value of 
the tablet and an x-y coordinate between them and the input device will normalize it to fit. 


The basic steps required are the same for all three methods. 


e Get a pointer to the screen where you want to position the pointer. This is not necessary for the 
tablet device. 


e Set up a structure to indicate the new position of the pointer. 


110 Amiga ROM Kernel Reference Manual: Devices 


For absolute and relative positioning, you set up an IEPointerPixel structure with iepp_Position.X 
set to the new x-coordinate, iepp_Position.Y set to the new y-coordinate and iepp_Screen set to the 
screen pointer. You set up an InputEvent structure with ie_SubClass set to ESUBCLASS_PIXEL, 
a pointer to the IEPointerPixel structure set in ie_EventAddress, ECLASS_NEWPOINTERPOS 
set in Class, and ie_Qualifier set to either EQUALIFIER-RELATIVEMOUSE for relative posi- 
tioning or NULL for absolute positioning. 


For tablet positioning, you set up an IEPointerTablet structure with iept_Range.X set to the 
maximum x-coordinate and iept_Range.Y set to the maximum y-coordinate, and iept_Value.X set 
to the new x-coordinate and iept_Value.Y set to the new y-coordinate. You set up an InputEvent 
structure with a pointer to the IEPointerTablet structure set in ie_EventAddress, ie_SubClass to 
IESUBCLASS_TABLET and Class set to ECLASS_NEWPOINTERPOS. 


Finally, for all three methods, pass an IOStdReq to the device with a pointer to the InputEvent 
structure set in io_Data and io_Command set to IND_WRITEEVENT. 


The following example sets the mouse pointer at an absolute position on a public screen using 
IECLASS_NEWPOINTERPOS. Notice that it uses V36 functions wherever possible. 


/ 


Set_Mouse.c 
This example sets the mouse at x=100 and y=200 
Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 


Requires Kickstart 36 or greater. 


% 0 0b 0 OF OE 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <devices/input.h> 
#include <devices/inputevent .h> 
#include <intuition/screens.h> 


#include <clib/exec_protos.h> 
#include <clib/intuition_protos.h> 


#include <stdio.h> 

#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#endif 

struct IntuitionBase *IntuitionBase; 


void main (void) 


struct IOStdReq *InputI0; /* I/O request block */ 

struct MsgPort *InputMP; /* Message port */ 

struct InputEvent *FakeEvent; /* InputEvent pointer */ 

struct IEPointerPixel *NewPixel; /* New mouse position pointer */ 
struct Screen *PubScreen; /* Screen pointer */ 


if (InputMP = CreateMsgPort ()) 


{ 
if ((FakeEvent 
(NewPixel 


AllocMem(sizeof (struct InputEvent),MEMF_PUBLIC)) && 
AllocMem(sizeof (struct IEPointerPixel),MEMF_PUBLIC)) ) 


{ 
if (InputIO = CreateIORequest (InputMP, sizeof (struct IOStdReq) ) ) 
if (!OpenDevice ("input.device", NULL, (struct IORequest *) InputIO, NULL) ) 
{ 
/* Open Intuition library */ 


if (IntuitionBase = (struct IntuitionBase *) 
OpenLibrary ("intuition. library", 36L) ) 


Input Device 111 


{ 

/* Get pointer to screen and lock screen */ 

if (PubScreen = (struct Screen *)LockPubScreen (NULL) ) 
{ 
/* Set up IEPointerPixel fields */ 
NewPixel->iepp Screen = (struct Screen *)PubScreen; /* WB screen */ 
NewPixel->iepp Position.X = 100; /* put pointer at x = 100 */ 
NewPixel->iepp Position.Y = 200; /* put pointer at y = 200 */ 


/* Set up InputEvent fields */ 

FakeEvent->ie_EventAddress = (APTR)NewPixel; /* IEPointerPixel */ 
FakeEvent->ie NextEvent = NULL; 

FakeEvent->ie Class = IECLASS NEWPOINTERPOS; /* new mouse pos */ 
FakeEvent->ie SubClass = IESUBCLASS PIXEL; /* on pixel */ 
FakeEvent->ie_ Code = IECODE_NOBUTTON; 

FakeEvent->ie Qualifier = NULL; /* absolute positioning */ 


InputIO->io Data = (APTR) FakeEvent; /* InputEvent */ 
InputIO->io Length = sizeof(struct InputEvent) ; 

Input IO->io Command = IND_WRITEEVENT; 

DolO((struct IORequest *) InputIO); 


/* Unlock screen */ 
UnlockPubScreen (NULL, PubScreen) ; 
} 


else 
printf("Could not get pointer to screen\n"); 


/* Close intuition library */ 
CloseLibrary (IntuitionBase) ; 


else 
printf("Error: Could not open V36 or higher intuition.library\n"); 


CloseDevice((struct IORequest *)InputIO); 
} 


else 
printf("Error: Could not open input.device\n"); 


DeleteIORequest (InputI0O) ; 
} 


else 
printf("Error: Could not create I/O request\n"); 


FreeMem(FakeEvent, sizeof (struct InputEvent) ); 
FreeMem(NewPixel, sizeof (struct IEPointerPixel)); 


} 


else 
printf("Error: Could not allocate memory for structures\n") ; 


DeleteMsgPort (InputMP) ; 
} 


else 
printf("Error: Could not create message port\n"); 


Setting the Key Repeat Threshold 


The key repeat threshold is the number of seconds and microseconds a user must hold down a key 
before it begins to repeat. This delay is normally set by the Preferences tool or by Intuition when 
it notices that the Preferences have been changed, but you can also do it directly through the input 
device. 


You set the key repeat threshold by passing a timerequest with IND_SETTHRESH set in 
io_Command and the number of seconds to delay set in tv_secs and the number of microsec- 
onds to delay set in tv_micro. 


112 Amiga ROM Kernel Reference Manual: Devices 


#include <devices/timer.h> 

struct timerequest *InputTime; /* Initialize with CreateExtIO() before using */ 
InputTime->tr_time.tv_secs=1; /* 1 second */ 
InputTime->tr_time.tv_micro=500000; /* 500000 microseconds */ 


InputTime->tr_node.io Command=IND_SETTHRESH; 
DoIO((struct IORequest *) InputTime) ; 


The code above will set the key repeat threshold to 1.5 seconds. 


Setting the Key Repeat Interval 


The key repeat interval is the time period, in seconds and microseconds, between key repeat events 
once the initial key repeat threshold has elapsed. (See “Setting the Key Repeat Threshold” above.) 
Like the key repeat threshold, this is normally issued by Intuition and preset by the Preferences tool. 


You set the key repeat interval by passing a timerequest with IND_SETPERIOD set in 
io_Command and the number of seconds set in tv_secs and the number of microseconds set 
in tv_micro. 


struct timerequest *InputTime; /* Initialize with CreateExtIO() before using */ 


InputTime->tr_time.tv_secs=0; 
InputTime->tr_time.tv_micro=12000; /* .012 seconds */ 
InputTime->tr_node.io Command=IND_SETPERIOD; 
DoIO((struct IORequest *) InputTime) ; 


The code above sets the key repeat interval to .012 seconds. 


The Right Tool For The Right Job. As previously stated, you must use a timerequest 
structure with IND_SETTHRESH and IND_SETPERIOD. 


Determining the Current Qualifiers 


Some applications need to know whether the user is holding down a qualifier key or a mouse 
button during an operation. To determine the current qualifiers, you call the input device function 
PeekQualifier(). 


PeekQualifier() returns what the input device considers to be the current qualifiers at the time 
PeekQualifier() is called (e.g., keyboard qualifiers and mouse buttons). This does not include any 
qualifiers which have been added, removed or otherwise modified by input handlers. 


In order to call the function, you must set a pointer to the input device base address. The pointer 
must be declared in the global data area of your program. Once you set the pointer, you can call the 
function. You must open the device in order to access the device base address. 


PeekQualifier() retums an unsigned word with bits set according to the qualifiers in effect at the 
time the function is called. It takes no parameters. 


Input Device 113 


struct Library *InputBase; 
VOID main(VOID) 
{ 


struct IOStdReq 
UWORD Quals; 


*InputI0O; 


/* Input device base address pointer */ 


/* I/O request block */ 
/* qualifiers */ 


if (!OpenDevice ("input.device", NULL, (struct IORequest *)InputIO, NULL) ) 
{ 


/* Set input device base address in InputBase */ 
InputBase = (struct Library *)InputIO->io_ Device; 


/* Call the function */ 
Quals = PeekQualifier(); 


CloseDevice (Input IO) ; 
} 
} 


The qualifiers returned are listed in the table below. 


2 
- 


Qualifier 


TEQUALIFIER_LSHIFT 
IEQUALIFIER_RSHIFT 
IEQUALIFIER_CAPSLOCK 
IEQUALIFIER_CONTROL 
TEQUALIFIER_LALT 
TEQUALIFIER_RALT 
IEQUALIFIER_LCOMMAND 
IEQUALIFIER_RCOMMAND 
IEQUALIFIER_MIDBUTTON 
IEQUALIFIER_RBUTTON 
IEQUALIFIER_LEFTBUTTON 


RoOonpDTAUNAWNHK OS 


Input Device and Intuition 


Key or Button 


Left Shift 
Right Shift 
Caps Lock 
Control 

Left Alt 
Right Alt 
Left-Amiga 
Right-Amiga 
Middle Mouse 
Right Mouse 
Left Mouse 


There are several ways to receive information from the various devices that are part of the input 
device. The first way is to communicate directly with the device. This method is not recommended 
while the input device task is running — which is most of the time. The second way is to become a 
handler for the stream of events which the input device produces. That method is shown above. 


The third method of getting input from the input device is to retrieve the data from the console 
device or from the IDCMP (Intuition Direct Communications Message Port). These are the preferred 
methods for applications in a multitasking environment because each application can receive juts its 
own input (i.e., only the input which occurs when one of its window is active). See the “Intuition” 
chapter of Amiga ROM Kernel Reference Manual: Libraries for more information on IDCMP 
messages. See the “Console Device” chapter of this manual for more information on console device 


YO. 


114 Amiga ROM Kernel Reference Manual: Devices 


Example Input Device Program 


% Oe OO OO OO Ot 


/ 


Swap Buttons.c 

This example swaps the function of the left and right mouse buttons 
The C code is just the wrapper that installs and removes the 
input.device handler that does the work. 


The handler is written in assembly code since it is important that 
handlers be as fast as possible while processing the input events. 


Compile and link as follows: 


SAS C 5.10: 
LC -bl -cfirst -v -w Swap Buttons.c 


Adapt assemble: 
HX68 InputHandler.a to InputHandler.o 


BLink: 
BLink from LIB:c.o+Swap_Buttons.otInputHandler.o LIB LIB:lc.lib LIB:amiga.lib TO Swap Buttons 


#include <exec/types.h> 

#include <exec/memory.h> 
#include <exec/interrupts.h> 
#include <devices/input.h> 
#include <intuition/intuition.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/intuition_protos.h> 


#include <stdio.h> 


#ifdef LATTICE 


int 
int 


CXBRK (void) { return(0); } /* Disable SAS CTRL/C handling */ 
chkabort (void) { return(0); } /* really */ 


#endif 


UBYTE NameString[]="Swap Buttons"; 


struct NewWindow mywin={50, 40,124,18,0,1,CLOSEWINDOW, 


ext 


WINDOWDRAG | WINDOWCLOSE | SIMPLE_REFRESH | NOCAREREFRESH, 
NULL, NULL, NameSt ring, NULL, NULL, 0,0, 0, 0,WBENCHSCREEN } ; 


ern VOID ButtonSwap(); 


extern struct IntuitionBase *IntuitionBase; 


/* 
* 
* 
* 


This routine opens a window and waits for the one event that 
can happen (CLOSEWINDOW) This is just to let the user play with 
the swapped buttons and then close the program... 


*/ 
VOID WaitForUser (VOID) 
{ 


struct Window ‘*win; 


if 


(IntuitionBase=(struct IntuitionBase *) 
OpenLibrary ("intuition. library", 33L) ) 


if (win=OpenWindow (&mywin) ) 


WaitPort (win->UserPort) ; 
ReplyMsg (GetMsg (win->UserPort) ); 


CloseWindow (win) ; 


} 
CloseLibrary((struct Library *)IntuitionBase) ; 


Input Device 115 


VOID main(VOID) 
{ 


struct I0StdReq *inputReqBlk; 
struct MsgPort *inputPort; 
struct Interrupt *inputHandler; 


if (inputPort=CreatePort (NULL, NULL) ) 


if (inputHandler=AllocMem(sizeof (struct Interrupt), 
MEMF_PUBLIC|MEMF_CLEAR) ) 


{ 
if (inputReqBlk=(struct IOStdReq *)CreateExtIO(inputPort, 
sizeof (struct IOStdReq) )) 


if (!OpenDevice ("input .device", NULL, 
(struct IORequest *) inputReqBlk, NULL) ) 
{ 


inputHandler->is Code=ButtonSwap; 
inputHandler->is Data=NULL; 
inputHandler->is Node.1n_Pri=100; 
inputHandler->is Node.1n Name=NameString; 
inputReqBlk->io_ Data=(APTR) inputHandler; 
inputReqBlk->io Command=IND_ADDHANDLER; 
DoIO((struct IORequest *) inputReqBlk) ; 


WaitForUser(); 


inputReqBlk->io_Data=(APTR) inputHandler; 
inputReqBl1k->io_Command=IND_REMHANDLER; 
DoIO((struct IORequest *)inputReqBlk) ; 


CloseDevice((struct IORequest *) inputReqBlk) ; 
} 


else 
printf("Error: Could not open input.device\n") ; 


DeleteExtIO((struct IORequest *) inputReqBlk) ; 
} 


else 
printf("Error: Could not create I/O request\n"); 


FreeMem(inputHandler, sizeof (struct Interrupt) ); 

} 
else 

printf("Error: Could not allocate interrupt struct memory\n"); 
DeletePort (inputPort) ; 
} 


else 
printf("Error: Could not create message port\n"); 
} 


FO OOOO III II III OI IOI IOI III II III IOI I kr 
InputHandler.a 


InputHandler that does a Left/Right mouse button swap... 


% 0 Oe Oe OF 


See Swap Buttons.c for details on how to compile/assemble/link... 


IOI IOI IO IOI OI IOI IO IOI III III III IOI kk kk kkk kk 
* 


* Required includes... 
* 


INCDIR "include:" 
INCLUDE "“exec/types.i" 
INCLUDE "exec/io.i" 


INCLUDE "devices/inputevent.i" 
* 


OI OOOO IOI IOI IOI IO III IOI II III kk tok keke 
* 


* Make the entry point external... 
* 


xdef _ButtonSwap 
* 


ok koko kook KKK KK KKK KKK KE KKK KKK RK KR KR KK KK 
* 


116 Amiga ROM Kernel Reference Manual: Devices 


* This is the input handler that will swap the 

* mouse buttons for left handed use. 

* 

* The event list gets passed to you in a0. 

* The is Data field is passed to you in al. 

* This example does not use the is Data field... 

* 

* On exit you must return the event list in dO. In this way 

* you could add or remove items from the event list. 

* 

* The handler gets called here... 

* 

* 

_ButtonSwap: move.l a0,-(sp) ; Save the event list 

¥ 

* Since the event list could be a linked list, we start a loop 

* here to handle all of the events passed to us. 

* 

CheckLoop: move.w ie Qualifier(a0),dl ; Get qualifiers... 
move.w dl1,d0 7; Two places... 

* 

* Since we are changing left and right mouse buttons, we need to make 

* sure that we change the qualifiers on all of the messages. The 

* left and right mouse buttons are tracked in the message qualifiers 

* for use in such things as dragging. To make sure that we continue 

* to drag correctly, we change the qualifiers. 

* 

CheckRight: btst #IEQUALIFIERB RBUTTON, dl ; Check for right 
beq.s NoRight 
bset #IEQUALIFIERB LEFTBUTTON, dO ; Set the left... 
beq.s CheckLeft 

NoRight: belr #IEQUALIFIERB_LEFTBUTTON, dO ; Clear the left... 

* 

CheckLeft: btst #IEQUALIFIERB LEFTBUTTON, dl ; Check for left 
beq.s NoLeft 
bset #IEQUALIFIERB RBUTTON, dO ; Set the right... 
beq.s SaveQual 

NoLeft: belr #IEQUALIFIERB_RBUTTON, dO 7; Clear the right... 

* 

SaveQual: move.w d0,ie Qualifier (a0) 7 Save back... 

* 

* The actual button up/down events are transmitted as the 

* code field in RAWMOUSE events. The code field must the be 

* checked and modified when needed on RAWMOUSE events. If the 

* event is not a RAWMOUSE, we are done with it. 

* 
cmp.b #IECLASS RAWMOUSE,ie Class(a0) ; Check for mouse 
bne.s NextEvent 7; If not, next... 

* 
move.w ie Code(a0),d0 ; Get code... 
move.w d0,dl ; Save... 
and.w #$7F,d0 ; Mask UP_PREFIX 
cmp.w #IECODE LBUTTON, dO ; Check for Left... 
beq.s SwapThem ; If so, swap... 
cmp.w #IECODE RBUTTON, dO ; Check for Right... 
bne.s NextEvent ; If not, next... 

* 

SwapThem: eor.w #1,dl1 + Flip bottom bit 
move.w dl,ie Code (a0) 7 Save it... 

* 

* The event list is linked via a pointer to the next event 

* in the first element of the structure. That is why it is not 

* nessesary to use: move.] ie NextEvent (a0) ,d0 

* 

* The reason I move to dO first is that this also checks for zero. 

* The last event in the list will have a NULL ie NextEvent field. 

* This is NOT as standard EXEC list where the node after the last 

* node is NULL. Input events are single-linked for performance. 

* 

NextEvent: move.l (a0),d0 ; Get next event 
move.l d0,a0 7 into a0... 
bne.s CheckLoop ; Do some more. 

* 

* All done, just return the event list... (in d0) 

* 


move.l (sp)+,d0 ; Get event list back... 
rts ; return from handler... 


Input Device 117 


Additional Information on the Input Device 


Additional programming information on the input device can be found in the include files and the 
autodocs for the input device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Input Device Information 


INCLUDES devices/input.h 
devices/input.i 


devices/inputevent.h 
devices/inputevent.i 


AUTODOCS input.doc 





118 Amiga ROM Kernel Reference Manual: Devices 


chapter seven 
KEYBOARD DEVICE 


The keyboard device gives low-level access to the Amiga keyboard. When you send this device the 
command to read one or more keystrokes from the keyboard, for each keystroke (whether key-up 
or key-down) the keyboard device creates a data structure called an input event to describe what 
happened. The keyboard device also provides the ability to do operations within the system reset 
processing (Ctrl-Amiga-Amiga). 


Keyboard Device 119 


Keyboard Device Commands and Functions 


Command Operation 


CMD_CLEAR Clear the keyboard input buffer. Removes any key transitions 
from the input buffer. 

KBD_ADDRESETHANDLER __ Add areset handler function to the list of functions called by 
the keyboard device to clean up before a hard reset. 

KBD_REMRESETHANDLER _ Remove a previously added reset handler from the list of 
functions called by the keyboard device to clean up before a 
hard reset. 

KBD_RESETHANDLERDONE Indicate that a handler has completed its job and reset could 
possibly occur now. 


KBD_READMATRIX Read the state of every key in the keyboard. Tells the up/down 
state of every key. 
KBD_READEVENT Read one (or more) raw key event from the keyboard device. 


Exec Functions as Used in This Chapter 


AbortIO() Abort a command to the keyboard device. 

AllocMem() Allocate a block of memory. 

CheckIO() Retum the status of an I/O request. 

CloseDevice() Relinquish use of the keyboard device. 

DoIOQ Initiate a command and wait for it to complete (synchronous request). 
FreeMem() Free a block of previously allocated memory. 

OpenDevice() Obtain use of the keyboard device. 

SendIOQ Initiate a command and retum immediately (asynchronous request). 
WaitIO() Wait for the completion of an asynchronous request. When the request is 


complete the message will be removed from reply port. 


Exec Support Functions as Used In This Chapter 


CreateExtIO(Q Create an extended I/O request structure. This structure will be used to 
communicate commands to the keyboard device. 

CreatePort() Create a signal message port for reply messages from the keyboard device. 
Exec will signal a task when a message arrives at the port. 

DeleteExtIO() Delete an extended I/O request structure created by CreateExtIO(). 

DeletePort() Delete the message port created by CreatePort(). 


120 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The keyboard device operates like the other Amiga devices. To use it, you must first open the 
keyboard device, then send I/O requests to it, and then close it when finished. See the “Introduction 
to Amiga System Devices” chapter for general information on device usage. 


The I/O request used by the keyboard device is called IOStdReq. 


struct IO0StdReq 
{ 


struct Message io Message; 


struct Device *io Device; /* device node pointer */ 

struct Unit *io Unit; /* unit (driver private) */ 

UWORD io_Command; /* device command */ 

UBYTE io Flags; 

BYTE io_Error; /* error or warning num */ 

ULONG io Actual; /* actual number of bytes transferred */ 
ULONG io_Length; /* requested number bytes transferred*/ 
APTR io Data; /* points to data area */ 

ULONG io_Offset; /* offset for block structured devices */ 


he 


See the include file exec/io.h for the complete structure definition. 


OPENING THE KEYBOARD DEVICE 


Three primary steps are required to open the keyboard device: 
e Create a message port using the CreatePort() function. 


e Create an extended I/O request structure using the CreateExtIO() function. CreateExtlOQ 
will initialize the I/O request with your reply port. 


e Open the keyboard device. Call OpenDevice(), passing the I/O request. 


struct MsgPort *KeyMP; /* Pointer for Message Port */ 
struct IOStdReq *KeyI0O; /* Pointer for I/O request */ 


if (KeyMP=CreatePort (NULL, NULL) ) 
if (KeyIO=(struct IOStdReq *) 
CreateExtIO(KeyMP, sizeof (struct IOStdReq)) ) 


if (OpenDevice ("keyboard.device",NULL, (struct IORequest *)KeyIO, NULL) ) 
printf ("keyboard.device did not open\n"); 


CLOSING THE KEYBOARD DEVICE 


An OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIO(Q and remove them with WaitIO(O. 
if (! (CheckIO(KeyI0) )) 

{ 

AbortIO(KeyIO); /* Ask device to abort request, if pending */ 


} 
WaitIO(KeyI0) ; /* Wait for abort, then clean up */ 
CloseDevice (KeyI0O) ; 


Keyboard Device 121 


Reading the Keyboard Matrix 


The KBD_READMATRIX command retums the current state of every key in the key matrix (up 
= 0, down = 1). You provide a data area that is at least large enough to hold one bit per key, 
approximately 16 bytes. The keyboard layout for the A500, A2000 and A3000 is shown in the 
figure below, indicating the raw numeric value that each key transmits when it is pressed. This 
value is the numeric position that the key occupies in the key matrix. 


a Lolate|s| «| Lalelalals| 


tet tee tet tell | 
esi pelzlalulsl|elolatefat «ls 





The following example will read the key matrix and display the up-down state of all of the elements 
in the matrix in a table. Reading the column header and then the row number as a hex number gives 
you the raw key code. 


/ 
Read Keyboard Matrix.c 


Compile with SAS C 5.10 le -bl -cfistq -v -y -L 


+ ee ee 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/libraries.h> 
#include <dos/dos.h> 

#include <devices/keyboard.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 
#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 

/* 


* There are keycodes from 0x00 to Ox7F, so the matrix needs to be 
* of 0x80 bits in size, or 0x80/8 which is 0x10 or 16 bytes... 

* / 

#define MATRIX_SIZE 16L 


/* 
* This assembles the matrix for display that translates directly 


* to the RAW key value of the key that is up or down 
*/ 


VOID Display Matrix(UBYTE *keyMatrix) 
{ 
SHORT bitcount; 


SHORT bytecount; 
SHORT mask; 


122 Amiga ROM Kernel Reference Manual: Devices 


USHORT twobyte; 
printf ("\n 012345 6 7"); 
printf("\n +----------------- Wye 
for (bitcount=0;bitcount<16;bitcount++) 
{ 
printf ("\n%x |", bitcount) ; 
mask=1 << bitcount; 
for (bytecount=0;bytecount <16;bytecount+=2) 
{ 
twobyte=keyMatrix[bytecount] | (keyMatrix[bytecount+1] << 8); 
if (twobyte & mask) 
printf (" *"); 


else 
printf(" -"); 


} 
printf ("\n\n"); 
} 


void main(int argc, char *argv[]) 

extern struct Library *SysBase; 

struct I0StdReq *KeyI0; 

struct MsgPort *KeyMP; 

UBYTE *keyMatrix; 

if (KeyMP=CreatePort (NULL, NULL) ) 

{ 
if (KeyIO=(struct IO0StdReq *)CreateExtIO(KeyMP, sizeof (struct IOStdReq) ) ) 
if (!OpenDevice ("keyboard.device", NULL, (struct IORequest *)KeyI0O, NULL) ) 
if (keyMatrix=AllocMem (MATRIX_SI ZE,MEMF_ PUBLIC |MEMF_CLEAR) ) 
{ 
Key10->io0_Command=KBD_READMATRIX; 
KeyIO->io_Data=(APTR) keyMatrix; 
KeyI0O->io_Length= SysBase->lib Version >= 36 ? MATRIX_SIZE : 13; 
DoIO((struct IORequest *)KeyI0O); 
/* Check for CLI startup... */ 
if (argc) 
Display Matrix (keyMatrix); 

FreeMem(keyMatrix,MATRIX_SIZE) ; 
} 


else 
printf("Error: Could not allocate keymatrix memory\") ; 


CloseDevice((struct IORequest *)KeyI0O); 


else 
printf("Error: Could not open keyboard.device\n") ; 


DeleteExtIO((struct IORequest *)KeyI0O); 
} 


else 
printf("Error: Could not create I/O request\n") ; 


DeletePort (KeyMP) ; 
} 


else 
printf("Error: Could not create message port\n"); 


In addition to the matrix data retumed in io_Data, io_Actual retums the number of bytes filled in 
io_Data with key matrix data, i.e., the minimum of the supplied length and the internal key matrix 
size. 

Value of io_Length. A value of 13 in the io_Length field will be sufficient for most 


keyboards; extended keyboards will require a larger number. However, you must always 
set this field to 13 for V34 and earlier versions of Kickstart. 


Keyboard Device 123 


To find the status of a particular key—for example, to find out if the F2 key is down—you find the 
bit that specifies the current state by dividing the key matrix value by 8. Since hex 51 = 81, this 
indicates that the bit is in byte number 10 of the matrix. Then take the same number (decimal 81) 
and use modulo 8 to determine which bit position within that byte represents the state of the key. 
This yields a value of 1. So, by reading bit position 1 of byte number 10, you determine the status 
of the function key F2. 


Amiga Reset Handling 


When a user presses the Ctrl key and both left- and right-Amiga keys simulataneously (the reset 
sequence), the keyboard device senses this and calls a prioritized chain of reset-handlers. These 
might be thought of as clean-up routines that “must” be performed before reset is allowed to occur. 
For example, if a disk write is in progress, the system should finish that before resetting the hardware 
SO as not to corrupt the contents of the disk. 


It is important to note that not all Amigas handle reset processing in the same way. On the A500, the 
reset key sequence sends a hardware reset signal and never goes through the reset handlers. Also 
some of the early A2000s (i.e., German keyboards with the function keys the same size as the Esc 
key) do not handle the reset via the reset handlers. It is thus recommended that your application not 
rely on the reset handler abilities of the keyboard device. 


ADDING A RESET HANDLER (KBD_ADDRESETHANDLER) 


The KBD_ADDRESETHANDLER command adds a custom routine to the chain of reset-handlers. 
Reset handlers are just like any other handler and are added to the handler list with an Interrupt 
structure. The priority field in the list node of the Interrupt structure establishes the sequence in 
which reset handlers are processed by the system. Keyboard reset handlers are currently limited to 
the priority values of a software interrupt, that is, values of -32, -16, 0, 16, and 32. 


The io_Data field of the I/O request is filled in with a pointer to the Interrupt structure and the 
io_Command field is set to KBD_ADDRESETHANDLER. These are the only two fields you need 
to initialize to add a reset handler. Any return value from the command is ignored. All keyboard 
reset handlers are activated if time permits. Normally, a reset handler will just signal the requisite 
task and return. The task then does whatever processing it needs to do and notifies the system that 
it is done by using the KBD_RESETHANDLERDONE command described below. 


Non-interference and speed are the keys to success. If you add your own handler 
to the chain, you must ensure that your handler allows the rest of reset processing to occur. 
Reset must continue to function. Also, if you don’t execute your reset code fast enough, 
the system will still reboot (about 10 seconds). 


REMOVING A RESET HANDLER (KBD_REMRESETHANDLER) 
This command is used to remove a keyboard reset handler from the system. You need to supply the 


same Interrupt structure to this command that you used with the KBD_ADDRESETHANDLER 
command. 


124 Amiga ROM Kernel Reference Manual: Devices 


ENDING A RESET TASK (KBD_RESETHANDLERDONE) 


This command tells the system that your reset handling code has completed. If you are the last 
outstanding reset handler, the system will reset after this call. 


Can't Stop, Got No Brakes. After 10 seconds, the system will reboot, regardless of 
outstanding reset handlers. 


Here is an example program that installs a reset handler and either waits for the reboot or for the 
user to close the window. If there was a reboot, the window will close and, if executed from the 
shell, it will display a few messages. If the user closes the window, the handler is removed and the 
program exits cleanly. 


/ 
Key Reset.c 


This is in two parts... 


Compile this C code with SAS C 5.10: 
le -bl -cfistq -v -y Key Reset 


Assemble the ASM code with Adapt 
HX68 KeyHandler.a to KeyHandler.o 


Link with: 
Blink FROM LIB:c.o+Key Reset.otKeyHandler.o TO Key Reset LIB LIB:lc.lib LIB:amiga.lib 
/ 


% 0% OF 0 > 0 OE OE OE OO OO 


/* 


* Keyboard device reset handler example... 
*/ 


#include <exec/types.h> 

#include <exec/io.h> 

#include <exec/ports.h> 

#include <exec/memory.h> 
#include <devices/keyboard.h> 
#include <intuition/intuition.h> 
#include <exec/interrupts.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/intuition_protos.h> 
#include <clib/dos_ protos.h> 


#include <stdio.h> 
#ifdef LATTICE 
int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
void main(); 
#fendif 
extern VOID ResetHandler (); 
UBYTE NameString[]="Reset Handler Test"; 
struct NewWindow mywin={0,0,178,10,0,1,CLOSEWINDOW, 
WINDOWDRAG | WINDOWCLOSE | SIMPLE_REFRESH| NOCAREREFRESH, 
NULL, NULL, NameSt ring, NULL, NULL, 0,0,0,0,WBENCHSCREEN}; 
extern struct IntuitionBase *IntuitionBase; 
struct MyData 
{ 
struct Task *MyTask; 
ULONG MySignal; 
Me 


/* 
* This routine opens a window and waits for the one event that 
* can happen (CLOSEWINDOW) 


Keyboard Device 125 


*/ 
short WaitForUser (ULONG MySignal) 


struct Window *win; 
short ret=0; 


if (IntuitionBase=(struct IntuitionBase *)OpenLibrary ("intuition.library", OL) ) 
{ 
if (win=(struct Window *) OpenWindow (&mywin) ) 


{ 
ret=(MySignal==Wait (MySignal | (1L << win->UserPort->mp_ SigBit))); 
CloseWindow (win) ; 
} 
else 
printf("Error: Could not open window\n") ; 
CloseLibrary((struct Library *)IntuitionBase) ; 


else 
printf("Error: Could not open intution.library\n"); 
return (ret); 


} 
VOID main(int argc, char *argv[]) 


{ 

struct I0StdReq *KeyI0O; 

struct MsgPort *KeyMP; 

struct Interrupt *keyHandler; 

struct MyData MyDataStuff; 
ULONG MySignal; 


if ((MySignal=AllocSignal (-1L)) !=-1) 
{ 


MyDataStuff.MyTask=FindTask (NULL) ; 
MyDataStuff.MySignal=1L << MySignal; 


if (KeyMP=CreatePort (NULL, NULL) ) 
{ 
if (keyHandler=AllocMem (sizeof (struct Interrupt) ,MEMF_PUBLIC|MEMF_ CLEAR) ) 
if (KeyIO=(struct IOStdReq *)CreateExtIO(KeyMP, sizeof (struct IOStdReq) ) ) 


{ 

if (!OpenDevice ("keyboard.device",NULL, (struct IORequest *)KeyIO, NULL) ) 
{ 
keyHandler->is_Code=ResetHandler; 
keyHandler->is_Data=(APTR) sMyDataStuff; 


/* 

* Note that only software interrupt priorities 
* can be used for the .1ln Pri on the reset 

* handler... 

*/ 
keyHandler->is_Node.1ln Pri=16; 


keyHandler->is_ Node.1n_ Name=NameString; 
KeyIO->io_Data=(APTR) keyHandler; 
KeyIO->io_Command=KBD_ADDRESETHANDLER; 
DoIO((struct IORequest *)KeyIO); 


if (WaitForUser (MyDataStuff.MySignal) )} 
{ 
if (argc) /* Check for CLI */ 
{ 


printf ("System going down\n"); 
printf ("Cleaning up...\n"); 

/* Show a delay, like cleanup... */ 
Delay (20); 

printf ("*Poof*\n") ; 


/* We are done with our cleanup */ 
KeyI0O->io Data=(APTR) keyHandler; 
KeyIO->io Command=KBD_RESETHANDLERDONE; 
DoIO((struct IORequest *)KeyI0O); 

/* 

* Note that since the above call 


* tells the system it is safe to reboot 
* and will cause the reboot if this 


126 Amiga ROM Kernel Reference Manual: Devices 


* task was the last to say so, the call 
* never really returns... The system 
* just reboots... 

* 


} 
KeyIO->io_Data=(APTR) keyHandler; 
KeyI0O->io Command=KBD_REMRESETHANDLER; 
DoIO((struct IORequest *)KeyIO); 
CloseDevice((struct IORequest *)KeyI0O); 
} 


else 
printf("Error: Could not open keyboard.device\n"); 


DeleteExtIO((struct IORequest *)KeyIO); 
} 


else 
printf("Error: Could not create I/O request\n"); 


FreeMem(keyHandler, sizeof (struct Interrupt) ); 


else 
printf("Error: Could not allocate memory for interrupt\n"); 


DeletePort (KeyMP) ; 
} 


else 
printf("Error: Could not create message port\n"); 


FreeSignal (MySignal) ; 
} 
else 


printf("Error: Could not allocate signal\n"); 
} 


PES SSSA SSSSSSESSSSSSSSSASESESE SSS SSESE SSL ESS SELES SE SESE SLES SSS SE SASS SSS SASS SS SS 
KeyHandler.a 


Keyboard reset handler that signals the task in the structure... 


% OF Oe 


See Key Reset.c for details on how to compile/assemble/link... 


* 


ROO RIO KIO III IOI IO IOI KKK KEK KK KK 
* Required includes... 
* 


INCDIR "include:" 

INCLUDE "exec/types.i" 
INCLUDE "exec/io.i" 

INCLUDE "devices/keyboard.i" 


xref AbsExecBase We get this from outside... 


xref ~LvoSignal 3; We get this from outside... 
* 


ROI OOOO IOI III IOI IOI Ok ick 


* Make the entry point external... 
* 


xdef _ResetHandler 
* 
FORK OI OI TORII III IO IO kk kik 
x 


* This is the input handler 
* The is Data field is passed to you in al. 
* 
* This is the structure that is passed in Al in this example... 
* 
STRUCTURE MyData, 0 
APTR MyTask 
ULONG MySignal 


* 

He HII II IK KK IK KI IK I IKK KKK KI KK IK KKK IKK KKK IK KK KKK KKK KKK KEK KEKE KK KKK 
* The handler gets called here... 

*x 


_ResetHandler: move.1 MySignal(al),d0 ; Get signal to send 


move.l MyTask(al),al ; Get task 
* 


* Now signal the task... 


Keyboard Device 127 


; Save the stack... 
Get ExecBase 
; Send the signal 


move.l a6,-(sp) 
move.l _AbsExecBase, a6 
jsr _LVOSignal (a6) 


Rese es 


move.l (sp)+,a6 ; Restore A6 
* 
* Return to let other handlers execute. 
* 
rts ; return from handler... 


* 


END 
TIO IOI IOI IOI III IOI III III IOI IOI IOI IOI III OI I ok kok 


Reading Keyboard Events 


Reading keyboard events is normally not done through direct access to the keyboard device. (Higher 
level devices such as the input device and console device are available for this. See the chapter “Input 
Device,” for more information on the intimate linkage between the input device and the keyboard 
device.) This section is provided primarily to show you the component parts of a keyboard input 
event. 


The keyboard matrix figure shown at the beginning of this chapter gives the code value that each 
key places into the ie_Code field of the input event for a key-down event. For a key-up event, a 
value of hexadecimal 80 is or’ed with the value shown above. Additionally, if either shift key is 
down, or if the key is one of those in the numeric keypad, the qualifier field of the keyboard input 
event will be filled in accordingly. In V34 and earlier versions of Kickstart, the keyboard device 
does not set the numeric qualifier for the keypad keys ‘(’, ‘)’, ‘/’, ‘*’ and ‘+’. 


When you ask to read events from the keyboard, the call will not be satisfied until at least one 
keyboard event is available to be retumed. The io_Length field must contain the number of bytes 
available in io_Data to insert events into. Thus, you should use a multiple of the number of bytes 
in an InputEvent (see example below). 


Type-Ahead Processing. The keyboard device can queue up several keystrokes without 
a task requesting a report of keyboard events. However, when the keyboard event buffer 
has been filled with no task interaction, additional keystrokes will be discarded. 


EXAMPLE READ KEYBOARD EVENT PROGRAM 


Shown below is an example keyboard.device read-event program: 


/ 


Keyboard Events.c 


This example does not work very well in a system where 

input.device is active since input.device also actively calls for 
keyboard events via this call. For that reason, you will not get all of 
the keyboard events. Neither will the input device; no one will be happy. 


Compile with SAS 5.10 lc -bl -cfistq -v -y -L 


0 OO 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/io.h> 

#include <exec/ports.h> 
#include <exec/memory.h> 
#include <devices/inputevent.h> 


128 Amiga ROM Kernel Reference Manual: Devices 


#include 


#include 
#include 


#include 


<devices/keyboard.h> 


<clib/exec_protos.h> 
<clib/alib protos.h> 


<stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); 


/* Disable SAS CTRL/C handling */ 


} 
int chkabort (void) { return(0); } /* really */ 


#endif 


VOID Display Event (struct InputEvent *keyEvent) 


{ 
printf ("Got key event: KeyCode: %2x Quailifiers: %4x\n", 


} 


keyEvent->ie_ Code, 
keyEvent->ie Qualifier); 


VOID main(int argc, char *argv[]) 


{ 


struct I0StdReq *keyRequest; 


struct MsgPort *keyPort; 
struct InputEvent *keyEvent; 
SHORT loop; 


if (keyPort=CreatePort (NULL, NULL) )} 


if (keyRequest=(struct I0StdReq *)CreateExtI0O(keyPort, sizeof (struct IOStdReq) )) 


if (!OpenDevice ("keyboard.device",NULL, (struct IORequest *)keyRequest, NULL) ) 
{ 


if (keyEvent=AllocMem(sizeof (struct InputEvent) ,MEMF_ PUBLIC) ) 
{ 
for (loop=0;loop<4;loop++) 


keyRequest->io_Command=KBD_READEVENT; 
keyRequest->io_Data=(APTR) keyEvent; 


/ 
We want 1 event, so we just set the 
length field to the size, in bytes 

of the event. For multiple events, 

set this to a multiple of that size. 
The keyboard device NEVER fills partial 
events... 


/ 


3 0 OF 0 OF OF 


keyRequest->io_Length=sizeof (struct InputEvent); 
DoIO((struct IORequest *) keyRequest) ; 


/* Check for CLI startup... */ 
if (argc) 
Display Event (keyEvent) ; 
FreeMem(keyEvent, sizeof (struct InputEvent) ); 


else 
printf("Error: Could not allocate memory for InputEvent\n"); 


CloseDevice((struct IORequest *)keyRequest) ; 
} 


else 


printf("Error: Could not open keyboard.device\n") ; 


DeleteExtIO((struct IORequest *)keyRequest) ; 
} 


else 


printf("Error: Could not create I/O request\n"); 


DeletePort (keyPort); 
} 


else 


printf("Error: Could not create message port\n"); 


} 


Keyboard Device 129 


Additional Information on the Keyboard Device 


Additional programming information on the keyboard device can be found in the include files for 
the keyboard and input devices and the Autodocs for the keyboard device. All are contained in the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs. 


Keyboard Device Information 


INCLUDES devices/keyboard.h 
devices/keyboard.i 
devices/inputevent.h 
devices/inputevent.i 


AUTODOCS keyboard.doc 





130 Amiga ROM Kernel Reference Manual: Devices 


chapter eight 
NARRATOR DEVICE 


This chapter describes the narrator device which, together with the translator library, provides 
all of the Amiga’s text-to-speech functions. The narrator device is used to produce high-quality 
human-like speech in real time. 


New Narrator Features for Version 2.0 


NDB_NEWIORB 
NDB_WORDSYNC 
NDB_SYLSYNC 
FOenthusiasm 
FOperturb 

Fladj 

F2adj 


F3adj 
Aladj 
A2adj 
A3adj 
articulate 
centralize 
centphon 
AVbias 
AFbias 
priority 


Description 


Flag 

Flag 

Flag 

narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 
narrator_rb field 





Function 


Use V37 features 

Synchronize speech/mouth on words 
Synchronize speech/mouth on syllables 
FO excursion factor 

Amount of FO perturbation 

F1 adjustment in +5% steps 

F2 adjustment in +5% steps 

F3 adjustment in +5% steps 

A1 adjustment in decibels 

A2 adjustment in decibels 

A3 adjustment in decibels 
Transition time multiplier 

Degree of vowel centralization 
Pointer to central ASCII phon 
Amplitude of voicing bias 
Amplitude of frication bias 

Priority while speaking 


Compatibility Warning: The new features for the 2.0 narrator device are not backwards 


compatible. 


Narrator Device 131 


Narrator Device Commands and Functions 


Command Operation 

CMD_FLUSH Purge all active and queued requests for the narrator device. 

CMD_READ Read mouth shapes associated with an active write from the narrator 
device. 

CMD_RESET Reset the narrator port to its initialized state. All active and queued I/O 
requests will be aborted. Restarts the device if it has been stopped. 

CMD_START Restart the currently active speech (if any) and resume queued I/O requests. 

CMD_STOP Stop any currently active speech and prevent queued I/O requests from 
Starting. 

CMD_WRITE Write a stream of characters to the narrator device and generate mouth 


movement data for reads. 


Exec Functions as Used in This Chapter 


AbortIOQ Abort a command to the narrator device. If the command is in progress, 
it is stopped immediately. If it is queued, it is removed from the queue. 

BeginIOQ) Initiate a command and retum immediately (asynchronous request). This 
is used to minimize the amount of system overhead. 

CloseDevice() Relinquish use of the narrator device. All requests must be complete. 

CheckIO() Retum the status of an I/O request. 

CloseLibrary() Relinquish use of a previously opened library. 

DoIOO Initiate a command and wait for completion (synchronous request). 
Should be used with care because it will not return control if the request 
does not complete. 

OpenDevice() Obtain use of the narrator device. 

OpenLibrary() Obtain use of a library. 

SendIO() Initiate a command and retum immediately (asynchronous request). 

WaitIOQ Wait for the completion of an asynchronous request. When the request is 


complete the message will be removed from reply port. 


Exec Support Functions as Used in This Chapter 


CreateExtIO() Create an extended I/O request structure of type narrator_rb. This 
structure will be used to communicate commands to the narrator device. 
CreatePort() Create a signal message port for reply messages from the narrator device. 
Exec will signal a task when a message arrives at the port. 
DeleteExtIO(Q) Delete an extended I/O request structure created by CreateExtIO(. 
DeletePort() Delete the message port created by CreatePort(). 


132 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The narrator device operates like all other Amiga devices. To use the narrator device, you must first 
open it. This initializes certain global areas, opens the audio device, allocates audio channels, and 
performs other housekeeping functions. Once open, the device is ready to receive I/O commands 
(most typically CMD_WRITE and CMD_READ). Finally, when finished, the user should close the 
device. This will free some buffers and allow the entire device to be expunged should the system 
require memory. See the “Introduction to Amiga System Devices” chapter for general information 
on device usage. 


The narrator device uses two extended I/O request structures: narrator_rb for write commands 
(to produce speech output) and mouth_rb for read commands (to receive mouth shape changes 
and word/syllable synchronization events). Both I/O request structures have been expanded (in a 
backwards compatible fashion) for the V37 narrator device with several new fields defined. 


struct narrator rb 


{ 


struct IOStdReq message; 


UWORD 
UWORD 
UWORD 
UWORD 
UBYTE 
UWORD 
UWORD 
UWORD 
UBYTE 
UBYTE 
UBYTE 
UBYTE 
UBYTE 
UBYTE 
BYTE 
BYTE 
BYTE 
BYTE 
BYTE 
BYTE 
UBYTE 
UBYTE 
char 
BYTE 
BYTE 
BYTE 
BYTE 


he 


rate; 
pitch; 
mode; 

sex; 
*ch_masks; 
nm_masks; 
volume; 
sampfreq; 
mouths; 
chanmask; 
numchan; 
flags; 
FOenthusiasm; 
FOperturb; 
Fladj; 
F2adj; 
F3adj; 
Aladj; 
A2adj; 
A3adj; 
articulate; 
centralize; 
*centphon; 
AVbias; 
AFbias; 
priority; 
padi; 


struct mouth rb 


struct 

UBYTE 

UBYTE 

UBYTE 

UBYTE 
}; 


narrator rb voice; 


width; 
height; 
shape; 
sync; 


Standard IORequest Block */ 
Speaking rate (words/minute) */ 
Baseline pitch in Hertz */ 
Pitch mode */ 
Sex of voice */ 
Pointer to audio allocation maps 


Number of audio allocation maps 
Volume. 0 (off) thru 64 x/ 
Audio sampling frequency */ 
If non-zero, generate mouths */ 


ee 
*/ 


Which ch mask used (internal - do not modify) */ 
Num ch masks used (internal- do not modify) */ 


New feature flags x/ 
FO excursion factor */ 
Amount of FO perturbation */ 
Fl adjustment in +- 5% steps 


F2 adjustment in +- 5% steps 


F3 adjustment in +- 5% steps 

Al adjustment in decibels */ 
A2 adjustment in decibels */ 
A3 adjustment in decibels */ 
Transition time multiplier x/ 


Degree of vowel centralization */ 


Pointer to central ASCII phon 


Amplitude of voicing bias */ 
Amplitude of frication bias */ 
Priority while speaking x/ 
For alignment */ 
Speech IORequest Block */ 


Mouth width (returned value) */ 
Mouth height (returned value) */ 
Internal use, do not modify */ 
Returned sync events */ 


Details on the meaning of the various fields of the two I/O request blocks can be found in the 
“Writing to the Narrator Device” and “Reading from the Narrator Device” sections later in this 
chapter. See the include file devices/narrator.h for the complete structure definitions. 


Narrator Device 133 


THE AMIGA SPEECH SYSTEM 


The speech system on the Amiga is divided into two subsystems: 


e The translator library, consisting of a single function: Translate(), which converts an English 
string into its phonetic representation, and 


e The narrator device, which uses the phonetic representation (generated either manually or by 
the translator library) as input to generate human-like speech and play it out via the audio 
device. 


The two subsystems can be used either together or individually. Generally, hand coding phonetic text 
will produce better quality speech than using the translator library, but this requires the programmer 
to “hard code” the phonetic text in the program or otherwise restrict the input to phonetic text only. 
If the program must handle arbitrary English input, the translator library should be used. 


Below is an example of how you would use the translator library to translate a string for the narrator 
device. 


#define BUFLEN 500 


APTR EnglStr; /* pointer to sample input string */ 
LONG EnglLen; /* input length */ 

UBYTE PhonBuffer[BUFLEN] ; /* place to put the translation */ 
LONG rtnCode; /* return code from function */ 
struct narrator rb *Voicel0; /* speaking I/O request block */ 
struct mouth_rb *MouthI0O; /* mouth movement I/O request block */ 
EnglStr = "This is Amiga speaking."; /* a test string */ 

EnglLen = strlen(EnglStr) ; 

rtnCode = Translate(EnglStr, EnglLen, (APTR) &PhonBuffer[0], BUFLEN); 
voice _io->message.io Command = CMD WRITE; 

voice _io->message.io Offset = 0; 

voice_io->message.io Data = PhonBuffer; 


voice io-~>message.io Length strlen (PhonBuf fer) ; 
DoIO((struct IORequest *)VoiceI0O) 


This chapter discusses only the narrator device; refer to the “Translator Library” chapter of the 
Amiga ROM Kernel Reference Manual: Libraries for more information on the translator library. 


While the narrator device on the Amiga supports all of the major device commands (see the Narrator 
Device Commands and Functions section), two of these commands do most of the work in the device. 
They are: 


e CMD_WRITE—This command is used to send a phonetic string to the device to be spoken. 
The narrator_rb I/O request block also contains several parameters which can be set to control 
various aspects of the speech, such as pitch, speaking rate, male/female voice, and so on. Some 
of the options are rather arcane. See the “Writing to the Narrator Device” section for a complete 
list of options and their descriptions. 


e CMD_READ—The narrator device can be told to generate various synchronization events 
which the user can query. These events are: mouth shape changes, word sync, and/or syllable 
sync. The events can be generated singly or in any combination, as requested by the user. 
Word and syllable synchronization events are new to system 2.0 and later (V37 and later of the 
narrator device). See the “Reading from the Narrator Device” section for more details. 


134 Amiga ROM Kernel Reference Manual: Devices 


OPENING THE NARRATOR DEVICE 


Three primary steps are required to open the narrator device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an extended I/O request structure of type narrator_rb. The narrator_rb structure is 
created by the CreateExtIO() function. 


e Open the narrator device. Call OpenDevice() passing the I/O request. 


struct MsgPort *VoiceMP; 
struct narrator rb *VoiceI0; 


if (VoiceMP = CreatePort ("speech write", 0)) 
if (VoiceIO = (struct narrator rb *) 
CreateExtI0(VoiceMP, sizeof (struct narrator _rb)); 
if (OpenDevice("narrator.device", 0, VoiceIO, 0)) 
printf ("narrator.device did not open\n"); 


When the narrator device is first opened, it initializes certain fields in the user’s narrator_rb I/O 
request structure. In order to maintain backwards compatibility with older versions of the narrator 
device, a mechanism was needed for the device to ascertain whether it was being opened with a 
V37 or pre-V37 style I/O request structure. The pad field in the pre-V37 narrator_rb I/O request 
structure (which no one should have ever touched!) has been replaced by the flags field in the 
V37 narrator_rb structure, and is our path to upward compatibility. The device checks to see 
if a bit is set in this flags field. This bit must be set before opening the device if V37 or later 
features of the narrator device are to be used. There are two defined constants in the include file, 
NDB_NEWIORB and NDF_NEWIORB. NDB_NEWIORB specifies the bit which must be set in 
the flags field, NDF_NEWIORB is the field definition of the bit (1 << NDB_NEWIORB). 


Once the device is opened, the mouth_rb (read) I/O request structure can be set up. Each 
CMD_READ request must be matched with an associated CMD_WRITE request. This is nec- 
essary for the device to match the various sync events with a particular utterance. The read I/O 
request structure is easily set up as follows: 


e Create a read message port using the CreatePort() function. 
e Allocate memory for the mouth_rb extended I/O request structure using AllocMem(). 


e Copy the narrator_rb I/O request structure used to open the device into the voice field of the 
mouth_rb I/O request structure. This will set the fields necessary for the device to make the 
correct correspondence between read and write requests. 


e Copy the pointer to the read message port retumed from CreatePort() into the 
voice.message.io_Message.mn_ReplyPort field of the mouth_rb structure. 


Narrator Device 135 


The following code fragment, in conjunction with the OpenDevice() code fragment above, shows 
how to set up the mouth_rb structure: 


struct MsgPort *MouthMP; 
struct mouth _rb *MouthI0O; 


if (MouthMP = CreatePort ("narrator read", 0)) 
if (!(MouthIO = (struct mouth _rb *) 
AllocMem(sizeof (struct mouth_rb),MEMF_PUBLIC|MEMF_CLEAR) ) ) 


{ 
MouthI0O->voice = *VoicelI0; /* Copy I/O request used in OpenDevice */ 
MouthI0O->voice.message.io Message.mn_ReplyPort = MouthMP; /* Set port */ 
} 

else 
printf ("AllocMem failed\n"); 

else 
printf ("CreatePort failed\n"); 


CLOSING THE NARRATOR DEVICE 


Each OpenDevice() must be eventually matched by a call to CloseDevice(). This is necessary to 
allow the system to expunge the device in low memory conditions. As long as any task has the 
device open, or has forgotten to close it before terminating, the narrator device will not be expunged. 


All I/O requests must have completed before the task can close the device. If any requests are still 
pending, the user must abort them before closing the device. 
if (! (CheckIO(VoiceIO) 


{ 
AbortIO(VoiceIO); /* Abort queued or in progress request */ 


} 
WaitIO((struct IORequest *)VoiceI0O); /* Wait for abort to do its job */ 
CloseDevice (VoicelI0O); /* Close the device */ 


Writing to the Narrator Device 


You write to the narrator device by passing a narrator_rb I/O request to the device with 
CMD_WRITE set in io_Command, the number of bytes to be written set in io_Length and 
the address of the write buffer set in io_Data. 


VoiceI0O->message.io Command = CMD WRITE; 
VoiceIlO->message.io Offset = 0; 
VoiceIlO->message.io Data = PhonBuffer; 


Voicel0O->message.io_ Length strlen (PhonBuffer) ; 
DoIO((struct IORequest *)VoiceI0O); 

You can control several characteristics of the speech, as indicated in the narrator_rb struct 
shown in the “Device Interface” section. 


Generally, the narrator device attempts to speak in a non-regional dialect of American English. With 
pre-V37 versions of the device, the user could change only a few of the more basic aspects of the 
speaking voice such as pitch, male/female, speaking rate, etc. With the V37 and later versions of the 
narrator device, the user can now change many more aspects of the speaking voice. In addition, in 
the pre-V37 device, only mouth shape changes could be queried by the user. With the V37 device, 
the user can also receive start of word and start of syllable synchronization events. These events 
can be generated independently, giving the user much greater flexibility in synchronizing voice to 
animation or other effects. 


136 Amiga ROM Kernel Reference Manual: Devices 


The following describes the fields of the narrator_rb structure: 


message.io_Data 
Points to a NULL-terminated ASCII phonetic input string. For backwards compatibility issues, 
the string may also be terminated with a ‘#’ symbol. See the “How to Write Phonetically for 
Narrator” section of this chapter for details. 


message.io_Length 
Length of the input string. The narrator device will parse the input string until either a NULL 
or a ‘#’ is encountered, or until io_Length characters have been processed. 


rate 
The speaking rate in words/minute. Range is from 40 to 400 wpm. 

pitch 
The baseline pitch of the speaking voice. Range is 65 to 320 Hertz. 

mode 
The FO (pitch) mode. ROBOTICFO produces a monotone pitch, NATURALFO produces a 
normal pitch contour, and MANUALFO (new for V37 and later) gives the user more explicit 
control over the pitch contour by creative use of accent numbers. In MANUALFO mode, a 
given accent number will have the same effect on the pitch regardless of its position in the 
sentence and its relation to other accented syllables. In NATURALFO mode, accent numbers 
have a reduced effect towards thé end of sentences (especially long ones). In addition, the 
proximity of other accented syllables, the number of syllables in the word, and the number of 
phrases and words in the sentence all affect the pitch contour. In MANUALFO mode these 
things are ignored and it’s up to the user to do the controlling. This has the advantage of being 
able to have the pitch be more expressive. The FOenthusiasm field will scale the effect. 


sex 
Controls the sex of the speaking voice (MALE or FEMALE). In actuality, only the formant 
targets are changed. The user must still change the pitch and speaking rate of the voice to get 
the correct sounding sex. See the include files for default pitch and rate settings. 


ch_masks 
Pointer to a set of audio allocation maps. See the ‘“‘Audio Device” chapter for details. 


nm_masks 
Number of audio allocation maps. See the “Audio Device” chapter for details. 


volume 
Sets the volume of the speaking voice. Range 0 - 64. 


sampfreq 
The synthesizer is “tuned” to a sampling frequency of 22,200 Hz. Changing sampfreq affects 
pitch and formant tunings and can be used to create unusual vocal effects. For V37 and later, 
it is recommended that F1, F2, and F3adj be used instead to achieve this effect. 


mouths 
If set to a non-zero value will direct the narrator device to generate mouth shape changes and 
send this data to the user in response to read requests. See the “Reading from the Narrator 
Device” section for more details. 


chanmask 
Used internally by the narrator device. The user should not modify this field. 


Narrator Device 137 


numchan 
Used internally by the narrator device. The user should not modify this field. 


flags (V37) 
Used to specify V37 features of the device. Possible bit settings are: 
NDB_NEWIORB - I/O request block uses V37 features. 
NDB_WORDSYNC - Device should generate start of word sync events. 
NDB_SYLSYNC - Device should generate start of syllable sync events. 
These bit definitions and their corresponding field definitions (NDF_-NEWIORB, 
NDF_WORDSYNC, and NDF_SYLSYNC) can be found in the include files. 


FOenthusiasm (V37) 
The value of this field controls the scaling of pitch (FO) excursions used on accented syllables 
and has the effect of making the narrator device sound more or less “enthusiastic” about what it 
is saying. It is calibrated in 1/32s with unity (32) being the default value. Higher values cause 
more FO variation, lesser values cause less. This feature is most useful in manual FO mode. 


FOperturb (V37) 
Non-zero values in this field cause varying amounts of random low-frequency modulation of 
the pitch (FO). In other words, the pitch shakes in much the same way as an elderly person’s 
voice does. Range is 0 to 255. 


Fladj, F2adj, F3adj (V37) 

Changes the tuning of the formant frequencies. A formant is a major vocal tract resonance, 
and the frequencies of these formants move continuously as we speak. Traditionally, they 
have been given the abbreviations of F1, F2, F3... with Fl being the one lowest in frequency. 
Moving these formants away from their normal positions causes drastic changes in the sound 
of the voice and is a very powerful tool in the creation of character voices. This adjustment 
is in +5% steps. Positive values raise the formant frequencies and vice versa. The default is 
zero. Use these adjustments instead of changing sampfreq. 


Aladj, A2adj, A3adj (V37) 

In a parallel formant synthesizer, the amplitudes of the formants need to be specified along 
with their frequencies. These fields bias the amplitudes computed by the narrator device. This 
is useful for creating different tonal balances (bass or treble), and listening to formants in 
isolation for educational purposes. The adjustments are calibrated directly in +1db (decibel) 
steps. Using negative values will cause no problems; use of positive numbers can cause 
clipping. If you want to raise an amplitude, try cutting the others the same relative amount, 
then bring them all up equally until clipping is heard, then back them off. This should produce 
an optimum setting. This field has a +31 to -32 db range and the value -32db is equivalent to 
-infinity, shutting that formant off completely. 


articulate (V37) 
According to the popular theories of speech production, we move our articulators (jaw, tongue, 
lips, etc.) smoothly from one “target” position to the next. These articulatory targets correspond 
to acoustic targets specified by the narrator device for each phoneme. The device calculates 
the time it should take to get from one target to the next and this field allows you to intervene 
in that process. Values larger than the default will cause the transitions to be proportionately 
longer and vice versa. This field is calibrated in percent with 100 being the default. For 
example, a value of SO will cause the transitions to take half the normal time, with the result 
being “sharper”, more deliberate sounding speech (not necessarily more natural). A value of 


138 Amiga ROM Kernel Reference Manual: Devices 


200 will cause the transitions to be twice as long, slurring the speech. Zero is a special value in 
the narrator device will take special measures to create no transitions at all and each phoneme 
will simply be abutted to the next. 


centralize (V37) 

This field together with centphon can be used to create regional accent effects by modifying 
vowel sounds. centralize specifies the degree (in percent) to which vowel targets are “pulled” 
towards the targets of the vowel specified by centphon. The default value of 0% indicates that 
each vowel in the utterance retains its own target values. The maximum value of 100% indicates 
that each vowel’s targets are replaced by the targets of the specified vowel. Intermediate values 
control the degree of interpolation between the utterance vowel’s targets and the targets of the 
vowel specified by centphon. 


centphon (V37) 
Pointer to an ASCII string specifying the vowel whose targets are used in the interpolation 
specified by centralize. The vowels which can be specified are: TY, IH, EH, AE, AA, AH, AO, 
OW, UH, ER, UW. Specifying other than these will result in an error code being retummed. 


AVbias, AFbias (V37) 

Controls the relative amplitudes of the voiced and unvoiced speech sounds. Voiced sounds 
are those made with the vocal cords vibrating, such as vowels and some consonants like y, r, 
w, and m. Unvoiced sounds are made without the vocal cords vibrating and use the sound of 
turbulent air, such as s, t, sh, and f. Some sounds are combinations of both such as z and v. 
AVbias and AFbias change the default amplitude of the voiced and unvoiced components of 
the sounds respectively. (AV stands for Amplitude of Voicing and AF stands for Amplitude 
of Frication). These fields are calibrated in +1db steps and have the same range as the other 
amplitude biases, namely +31 to -32 db. Again, positive values may cause clipping. Negative 
values are the most useful. 


priority (V37) 

Task priority while speaking. When the narrator device begins to synthesize a sentence, the 
task priority remains unchanged while it is calculating acoustic parameters. However, when 
speech begins at the end of this process, the priority is bumped to 100 (the default value). If 
you wish, you may change this to anything you want. Higher values will tend to lock out most 
anything while speech is going on, and lower values may cause audible breaks in the speech 
output. The following example shows how to issue a write request to the narrator device. The 
first write is done with the default parameter settings. The second write is done after modifying 
the first and third formant loudness and using the centralization feature. 


The following example shows how to issue a write request to the narrator device. The first write 
is done with the default parameter settings. The second write is done after modifying the first and 
third formant loudness and using the centralization feature. 

/ 


Speak _Narrator.c 


This example program sends a string of phonetic text to the narrator 
device twice, changing some of the characteristics the second time. 


Compile with SAS C 5.10 le -bl -cfistq -v -y -L 


+ he OE OE 


Requires Kickstart V37 or greater. 
/ 


#include <exec/types.h> 


Narrator Device 139 


#include <exec/exec.h> 
#include <dos/dos.h> 
#include <devices/narrator.h> 


#include <clib/exec_protos.h> 
#include <clib/alib_protos.h> 
#include <clib/dos_protos.h> 


#include <string.h> 
#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#endif 


void main(void) 


struct MsgPort *VoiceMP; 

struct narrator rb *Voicel0; 

UBYTE *PhoneticText = "DHIHS IHZ AHMIYSGAH SPIYSKIHNX."; 
BYTE audio _chan[4] = {3, 5, 10, 12}; 


/* Create the message port */ 
if (VoiceMP=CreateMsgPort ()) 
{ 


/* Create the I/O request */ 
if (VoiceIO = CreatelORequest (VoiceMP, sizeof (struct narrator rb))) 
{ 
{[* Set the NEWIORB bit in the flags field to use the new fields */ 
VoicelO->flags = NDF_NEWIORB; 


/* Open the narrator device */ 
if (OpenDevice ("narrator.device",0, (struct IORequest *)VoiceI0O, OL) ) 


/* Inform user that it could not be opened */ 
printf("Error: narrator.device did not open\n"); 


else 


/* Speak the string using the default parameters */ 
Voicel0O->ch_masks = &audio chan[0]; 
VoiceIO->nm_masks = sizeof (audio chan); 
VoiceIO->message.io Command = CMD WRITE; 
VoiceIO->message.io Data = PhoneticText; 
VoiceIO->message.io_ Length = strlen(PhoneticText) ; 
DoIO(VoicelI0); 


/* Now change some of the characteristics: 


* Raise the first formant, lower the third formant, 

= and move 50% of the way towards AO. 

* and speak it again. 

*/ 
VoiceIO->Aladj = -32; /* Shut off first formant */ 
Voicel0O->A3adj = 11; /* Raise the third formant */ 
VoicelO->centralize = 50; /* Move 50% of the way */ 
VoicelO->centphon = "AO"; /* towards AO x/ 


DoIO(VoicelI0O) ; 


/* Close the narrator device */ 
CloseDevice((struct IORequest *)VoiceI0O); 


} 
/* Delete the IORequest */ 
DeleteIORequest (VoiceI0) ; 
} 


else 
/* Inform user that the I/O request could be created */ 
printf("Error: Could not create I/O request\n"); 


/* Delete the message port */ 
DeleteMsgPort (VoiceMP) ; 
} 


else 
/* Inform user that the message port could not be created */ 
printf("Error: Could not create message port\n"); 


140 Amiga ROM Kernel Reference Manual: Devices 


Reading from the Narrator Device 


All read requests to the narrator device must be matched to an associated write request. This is 
done by copying the narrator_rb structure used in the OpenDevice() call into the voice field of the 
mouth_rb I/O request structure. You must do this after the call to OpenDevice(). Matching the 
read and write requests allows the narrator device to coordinate I/O requests across multiple uses 
of the device. 


In pre-V37 versions of the narrator device, only mouth shape changes can be queried from the 
device. This is done by setting the mouths field of the narrator_rb I/O request structure (the write 
request) to a non-zero value. The write request is then sent asynchronously to the device and while 
it is in progress, synchronous read requests are sent to the device using the mouth_rb I/O request 
structure. When the mouth shape has changed, the device will return the read request to the user 
with bit O set in the sync field of the mouth_rb. The fields width and height of the mouth_rb 
structure will contain byte values which are proportional to the actual width and height of the mouth 
for the phoneme currently being spoken. Read requests sent to the narrator device are not returned 
to the user until one of two things happen: either the mouth shape has changed (this prevents the 
user from having to constantly redraw the same mouth shape), or the speech has completed. The 
user can check io_Error to determine if the mouth shape has changed (a return code of 0) or if the 
speech has completed (return code of ND_NoWrite). 


In addition to returning mouth shapes, reads to the V37 narrator device can also perform two new 
functions: word and syllable sync. To generate word and/or syllable sync events, the user must 
specify several bits in the flags field of the write request (narrator_rb structure). The bits are 
NDB_WORDSYNC and NDB_SYLSYNC, for start of word and start of syllable synchronization 
events, respectively, and, of course, NDB_NEWIORB, to indicate that the V37 I/O request is 
required. 


NDB_WORDSYNC and NDB_SYLSYNC tell the device to expect read requests and to generate the 
appropriate event(s). As with mouth shape change events, the write request is sent asynchronously 
to the device and, while it is in progress, synchronous read requests are sent to the device. The sync 
field of the mouth_rb structure will contain flags indicating which events (mouth shape changes, 
word sync, and/or syllable sync) have occurred. 


The returned sync field flags are: 
bit 0 (0x01) => mouth shape change event 
bit 1 (0x02) => start-of-word synchronization event 
bit 2 (0x04) => start-of-syllable synchronization event 


and 1 or more flags may be set for any particular read. 


As with mouth shape changes, read requests will not return until the requested event(s) have 
occurred, and the user must test the io_Error field of the mouth_rb structure to tell when the 
speech has completed (an error retum of ND_NoWrite). 


Several read events can be compressed into a single event. This can occur in two ways: first when 
two dissimilar events occur between two successive read requests. For example, a single read may 
retum both a mouth change and a syllable sync event. This should not present a problem if the 
user checks for all events. The second is when multiple events of the same type occur between 
successive read requests. This is of no great concem in dealing with mouth shape changes because, 
presumably, mouth events are used to drive animation, and the animation procedure will simply 
draw the current mouth shape. 


Narrator Device 141 


Watch Those Sync Events. When word or syllable sync is desired, the narrator device 
may compress multiple sync events into a single sync event. Missing a word or syllable 
sync may cause word highlighting (for example) to lose sync with the speech output. A 
future version of the device will include an extension to the mouth_rb I/O request structure 
which will contain word and syllable counts and, possibly, other synchronization methods. 


The following code fragment shows the basics of how to perform reads from the narrator device. 
For a more complete example, see the sample program at the end of this chapter. For this fragment, 
take the code of the previous write example as a starting point. Then the following code would 
need to be added: 


struct mouth_rb *MouthI0O; /* Pointer to read I0Request block */ 
struct MsgPort *MouthMP; /* Pointer to read message port x/ 
/* 


* (1) Create a message port for the read request. 
* 


if (!(MouthMP = CreatePort ("narrator read", OL))) 
BellyUp("Read CreatePort failed"); 


/* 

* (2) Create an extended I0Request of type mouth_rb. 

x7, 

if (!(MouthIO = (struct mouth_rb *)CreateExtIO(MouthMP, sizeof (struct mouth_rb)))) 
BellyUp("Read CreateExtIO failed"); 


/* 
* (3) Set up the read IORequest. Must be done after the call to OpenDevice(). 
7 We assume that the write IORequest and the OpenDevice have been done 
*/ 

MouthIO->voice = *SpeakIO; 


Mouth10->voice.message.io Message.mn_ReplyPort = ReadMsgPort; 
MouthI0->voice.message.io Command = CMD_READ; 


/* 


* (4) Set the flags field of the narrator_rb write request to return the desired 
syne events. If mouth shape changes are required, then the mouths field 


* of the IORequest should be set to a non-zero value. 
*/ 
SpeakI0O->mouths = 1; /* Generate mouth shape changes */ 
SpeakIO->flags = NDF_NEWIORB | /* Indicates V37 style IORequest */ 
NDF_WORDSYNC | /* Request start-of-word sync events */ 
NDF_SYLSYNC; /* Request start-of-syllable sync events */ 
/* 


* (5) Issue asynchronous write request. The driver initiates the write request 
*. and returns immediately. 


*/ 
SendI0O (SpeakI0O) ; 


/* 
* (6) Issue synchronous read requests. For each request we check the sync field 
7 to see which events have occurred. Since any combination of events can 
* be returned in a single read, we must check all possibilities. We 
*. continue looping until the read request returns an error of ND_NoWrite, 

* which indicates that the write request has completed. 
*/ 


for (DoIO(MouthIO) ;MouthI0->voice.message.io Error != ND_NoWrite;DoIO(MouthI0) ) 


{ 

if (MouthIO->sync & 0x01) DoMouthShape(); 
if (MouthIO->syne & 0x02) DoWordSync(); 

if (MouthIO->sync & 0x04) DoSyllableSync(); 
} 


/* 
* (7) Finally, we must perform a WaitIO() on the original write request. 
* 


WaitIO(SpeakI0O) ; 


142 Amiga ROM Kernel Reference Manual: Devices 


How to Write Phonetically for Narrator 


This section describes in detail the procedure used to specify phonetic strings to the narrator speech 
synthesizer. No previous experience with phonetics is required. The only thing you may need is a 
good pronunciation dictionary for those times when you doubt your own ears. You do not have to 
learn a foreign language or computer language. You are just going to lear how to write down the 
English that comes out of your own mouth. In writing phonetically you do not have to know how a 
word is spelled, just how it is said. 


Table of Phonemes 


Vowels 
Phoneme Example Phoneme Example 
IY beet, eat IH bit, in 
EH bet, end AE bat, ad 
AA bottle, on AH but, up 
AO ball, awl UH book, soot 
ER bird, early OH border 
AX* about, calibrate Ix* solid, infinite 


* AX and IX should never be used in stressed syllables. 


Diphthongs 
Phoneme Example Phoneme Example 
EY bay,aid AY bide,I 
OY boy,oil AW bound,owl 
OW boat,own UW brew,boolean 
Consonants 
Phoneme Example Phoneme Example 
R red L long 
W wag Y yellow,comp(Y)uter 
M men N no 
NX sing SH shy 
S soon TH thin 
F fed ZH pleasure 
Z has,zoo DH then 
Vv very WH when 
CH check J judge 
/H hole IC loch 
B but P put 
D dog T toy 
K keg,copy G guest 


Narrator Device 143 


Special Symbols 


Phoneme Example Explanation 


DX pity tongue flap 
Q kitt(Q)en glottal stop 
QX silent vowel 


Contractions (see text) 


UL = AXL 
IL = IXL 
UM = AXM 
IM = IXM 
UN = AXN 
IN = IXN 


Digits and Punctuation 


Digits 1-9 Syllabic stress, ranging from secondary through emphatic 
3 Period - sentence final character. 

? Question mark - sentence final character 

- Dash - phrase delimiter 

‘ Comma - clause delimiter 

O Parentheses - noun phrase delimiters (see text) 


The narrator device works on utterances at the sentence level. Even if you want to say only one 
word, it will treat it as a complete sentence. Therefore, narrator wants one of two punctuation marks 
to appear at the end of every sentence - a period or a question mark. The period is used for almost 
all utterances and will cause a final fall in pitch to occur at the end of a sentence. The question mark 
is used at the end of yes/no questions only, and results in a final rise in pitch. 


For example, the question, Do you enjoy using your Amiga? would take a question mark at the end, 
while the question, What is your favorite color? should be followed (in the phonetic transcription) 
with a period. If no punctuation appears at the end of a string, narrator will append a dash to it, 
which will result in a short pause. Narrator recognizes other punctuation marks as well, but these 
are left for later discussion. 


PHONETIC SPELLING 


Utterances are usually written phonetically using an alphabet of symbols known as IPA (International 
Phonetic Alphabet). This alphabet is found at the front of most good dictionaries. The symbols can 
be hard to learn and were not readily available on computer keyboards, so the Advanced Research 
Projects Agency (ARPA) came up with the ARPABET, a way of representing each symbol using one 
or two upper case letters. Narrator uses an expanded version of the ARPABET to specify phonetic 
sounds. 


A phonetic sound, or phoneme, is a basic speech sound, a speech atom. Working backwards: 
sentences can be broken into words, words into syllables, and syllables into phonemes. The word 


144 Amiga ROM Kernel Reference Manual: Devices 


cat has three letters and (coincidentally) three phonemes. Looking at the table of phonemes we 
find the three sounds that make up the word cat. They are the phonemes K, AE, and T, written 
as KAET. The word cent translates as SEHNT. Notice that both words begin with the letter c, but 
because they are pronounced differently they have different phonetic spellings. These examples 
introduce a very important concept of phonetic spelling: spell it like it sounds, not like it looks. 


Choosing the Right Vowel 


Phonemes, like letters, are divided into two categories: vowels and consonants. Loosely defined, 
a vowel is a continuous sound made with the vocal cords vibrating and air exiting the mouth (as 
opposed to the nose). A consonant is any other sound, such as those made by rushing air (like S or 
TH), or by interruptions in the air flow by the lips or tongue (B or T). All vowels use a two letter 
ASCII phonetic code while consonants use a one or two letter code. 


In English we write with only five vowels: a, e, i, 0, and u. It would be easy if we only said five 
vowels. However, we say more than 15 vowels. Narrator provides for most of them. Choose the 
proper vowel by listening: Say the word aloud, perhaps extending the vowel sound you want to 
hear and then compare the sound you are making to the sounds made by the vowels in the examples 
on the phoneme list. For example, the a in apple sounds the same as the a in cat, not like the a in 
Amiga, talk, or made. Notice also that some of the example words in the list do not even use any of 
the same letters contained in the phoneme code; for example AA as in bottle. 


Vowels are divided into two groups: those that maintain the same sound throughout their durations 
and those that change their sound. The ones that change are called diphthongs. Some of us were 
taught the terms long and short to describe vowel sounds. Diphthongs fall into the long category, 
but these two terms are inadequate to fully differentiate between vowels and should be avoided. 
The diphthongs are the last six vowels listed in the table. Say the word made out loud very slowly. 
Notice how the a starts out like the e in bet but ends up like the e in beet. The a, therefore, is a 
diphthong in this word and we would use EY to represent it. Some speech synthesis systems require 
you to specify the changing sounds in diphthongs as separate elements, but narrator takes care of 
the assembly of diphthongal sounds for you. 


Choosing the Right Consonant 


Consonants are divided into many categories by phoneticians, but we need not concern ourselves 
with most of them. Picking the correct consonant is very easy if you pay attention to just two 
categories: voiced and unvoiced. A voiced consonant is made with the vocal cords vibrating, and 
an unvoiced one is made when the vocal cords are silent. Sometimes English uses the same letter 
combinations to represent both. Compare the th in thin with the th in then. Notice that the first 
is made with air rushing between the tongue and upper teeth. In the second, the vocal cords are 
vibrating also. The voiced th phoneme is DH and the unvoiced one is TH. Therefore, thin is 
phonetically spelled as THIHN while the word then is spelled DHEHN. 


A sound that is particularly subject to mistakes is voiced and unvoiced s, phonemes Z and S, 
respectively. Clearly the word bats ends with an S and the word has ends with a Z. But, how do 
you spell close? If you say “What time do you close?”, you spell it with a Z, and if you are saying 
“T love to be close to you.” you use an S.” 


Another sound that causes some confusion is the r sound. There are two different r-like phonemes 
in the Narrator alphabet: R under the consonants and ER under the vowels. Use ER if the r sound 
is the vowel sound in the syllable like in bird, absurd, and flirt. Use the R if the r sound precedes 
or follows another vowel sound in that syllable as in car, write, and craft. 


Narrator Device 145 


Contractions and Special Symbols 


There are several phoneme combinations that appear very often in English words. Some of these 
are caused by our laziness in pronunciation. Take the word connector for example. The o in the 
first syllable is almost swallowed out of existence. You would not use the AA phoneme; you would 
use the AX phoneme instead. It is because of this relaxation of vowels that we find ourselves using 
AX and IX very often. Since this relaxation frequently occurs before /, m, and n, narrator has a 
shortcut for typing these combinations. Instead of personal being spelled PERSIXNAXL, we can 
spell it PERSINUL, making it a little more readable. Anomaly goes from AXNAAMAXLIY to 
UNAAMULIY, and KAAMBIXNEYSHIXN becomes KAAMBINEYSHIN for combination. It 
may be hard to decide whether to use the AX or IX brand of relaxed vowel. The only way to find 
out is to use both and see which sounds best. 


Other special symbols are used internally by narrator. Sometimes they are inserted into or substituted 
for part of your input sentence. You can type them in directly if you wish. The most useful is 
probably the Q or glottal stop, an interruption of air flow in the glottis. The word Atlantic has one 
between the t and the /. Narrator knows there should be a glottal stop there and saves you the trouble 
of typing it. But narrator is only close to perfect, so sometimes a word or word pair might slip by 
that would have sounded better with a Q stuck in someplace. 


STRESS AND INTONATION 


It is not enough to tell narrator what you want said. For the best results you must also tell narrator 
how you want it said. In this way you can alter a sentence’s meaning, stress important words, and 
specify the proper accents in polysyllabic words. These things improve the naturalness and thus the 
intelligibility of the spoken output. 


Stress and intonation are specified by the single digits 1-9 following a vowel phoneme code. Stress 
and intonation are two different things, but are specified by a single number. 


Stress is, among other things, the elongation of a syllable. A syllable is either stressed or not, so 
the presence of a number after the vowel in a syllable indicates stress on that syllable. The value of 
the number indicates the intonation. These numbers are referred to here as stress marks but keep in 
mind that they also affect intonation. 


Intonation here means the pitch pattern or contour of an utterance. The higher the stress mark, the 
higher the potential for an accent in pitch. A sentence’s basic contour is comprised of a quickly 
rising pitch gesture up to the first stressed syllable in the sentence, followed by a slowly declining 
tone throughout the sentence, and finally, a quick fall to a low pitch on the last syllable. The presence 
of additional stressed syllables causes the pitch to break its slow, declining pattern with rises and 
falls around each stressed syllable. Narrator uses a very sophisticated procedure to generate natural 
pitch contours based on how you mark the stressed syllables. 


How and Where to Put the Stress Marks 


The stress marks go immediately to the right of vowel phoneme codes. The word cat has its stress 
marked after the AE, e.g., KAEST. You generally have no choice about the location of a number; 
there is definitely a right and wrong location. A number should either go after a vowel or it should 
not. Narrator will not flag an error if you forget to put a stress mark in or if you place it on the 


146 Amiga ROM Kernel Reference Manual: Devices 


wrong vowel. It will only tell you if a stress mark has been put after a non-vowel, i.e., consonant 
or punctuation. 


The rules for placing stress marks are as follows: 


e Always place a stress mark in a content word. A content word is one that contains some 
meaning. Nouns, verbs, and adjectives are all content words, they tell the listener what you 
are talking about. Words like but, if, and the are not content words. They do not convey any 
real world meaning, but are required to make the sentence function, so they are given the name 
function words. 


e Always place a stress mark on the accented syllable(s) of polysyllabic words, whether they 
are content or function words. A polysyllabic word is any word of more than one syllable. 
Commodore has its stress (often called accent) on the first syllable and would be spelled 
KAASMAXDOHR, while computer is stressed on the second syllable: KUMPYUWSTER. 


If you are in doubt about which syllable gets the stress, look up the word in a dictionary and you will 
find an accent mark over the stressed syllable. If more than one syllable in a word receives stress, 
they usually are not of equal value. These are referred to as primary and secondary stresses. The 
word understand has its first and last syllables stressed, with the syllable stand getting the primary 
Stress and the syllable un getting the secondary stress. This produces the phonetic representation 
AH1INDERSTAEAND. Syllables with secondary stress should be marked with a value of only 1 or 
2: 


Compound words (words with more than one root) such as baseball, software, and lunchwagon can 
be written as one word, but should be thought of as separate words when marking stress. Thus, 
lunchwagon would be spelled LAHSNCHWAE2GIN. Notice that the lunch got a higher stress 
mark than the wagon. This is common in compound words, the first word usually receives the 
primary stress. 


Which Stress Value Do | Use? 


If you get the spelling and stress mark positions correct, you are 95 percent of the way to a good 
sounding sentence. The next thing to do is decide on the stress mark values. They can be roughly 
related to parts of speech, and you can use the table shown below as a guide to assigning values. 


Recommended Stress Values 
Part of Speech Stress Value 


Exclamations 
Adverbs 
Quantifiers 
Nouns 
Adjectives 
Verbs 
Pronouns 
Secondary stress lor2 
Everything else None 


wWwkhaAnnn”so 


Narrator Device 147 


The above values merely suggest a range. If you want attention directed to a certain word, raise 
its value. If you want to downplay a word, lower it. Sometimes even a function word can be the 
focus of a sentence. It is quite conceivable that the word to in the sentence Please deliver this to 
Mr. Smith. could receive a stress mark of 9. This would add focus to the word, indicating that the 
item should be delivered to Mr. Smith in person. 


PUNCTUATION 


In addition to the period or question mark that is required at the end of a sentence, Narrator also 
recognizes dashes, commas, and parentheses. 


The comma goes where you would normally put a comma in an English sentence. It causes narrator 
to pause with a slightly rising pitch, indicating that there is more to come. The use of additional 
commas—that is, more than would be required for written English—is often helpful. They serve to 
set clauses off from one another. There is a tendency for a listener to lose track of the meaning of a 
sentence if the words run together. Read your sentence aloud while pretending to be a newscaster. 
The locations for additional commas should leap out at you. 


The dash serves almost the same purpose as the comma, except that the dash does not cause the 
pitch to rise so severely. A rule of thumb is: Use dashes to divide phrases and commas to divide 
clauses. 


Parentheses provide additional information to narrator’s intonation function. They should be put 
around noun phrases of two or more content words. This means that the noun phrase, a giant yacht 
should be surrounded with parentheses because it contains two content words, giant and yacht. The 
phrase my friend should not have parentheses around it because it contains only one content word. 
Noun phrases can get fairly large, like the best time I’ ve ever had or a big basket of fruit and nuts. 
The parentheses are most effective around these large phrases; the smaller ones can sometimes 
go without. The effect of parentheses is subtle, and in some sentences you might not notice their 
presence. In sentences of great length, however, they help provide for a very natural contour. 


HINTS FOR INTELLIGIBILITY 


There are a few tricks you can use to improve the intelligibility of a sentence. Often, a polysyllabic 
word is more recognizable than a monosyllabic word. For instance, instead of saying huge, say 
enormous. The longer version contains information in every syllable, thus giving the listener a 
greater chance to hear it correctly. 


Another good practice is to keep sentences to an optimal length. Writing for reading and writing for 
speaking are two different things. Try not to write a sentence that cannot be easily spoken in one 
breath. Such a sentence tends to give the impression that the speaker has an infinite lung capacity 
and sounds unnatural. Try to keep sentences confined to one main idea; run-on sentences tend to 
lose their meaning. 


New terms should be highly stressed the first time they are heard. This gives the listener something 
to cue on, and can aid in comprehension. 


The insertion of the glottal stop phoneme Q at the end of a word can sometimes help prevent 
slurring of one word into another. When we speak, we do not pause at the end of each word, but 


148 Amiga ROM Kernel Reference Manual: Devices 


instead transition smoothly between words. This can sometimes reduce intelligibility by eliminating 
word boundary cues. Placing a Q, (not the silent vowel QX) at the end of a word results in some 
phonological effects taking place which can restore the word boundary cues. 


EXAMPLE OF ENGLISH AND PHONETIC TEXTS 


Cardiomyopathy. I had never heard of it before, but there it was listed as the form of heart disease 
that felled not one or two but all three of the artificial heart recipients. A little research produced 
some interesting results. According to an article in the Nov. 8, 1984, New England Journal of 
Medicine, cigarette smoking causes this lethal disease that weakens the heart’s pumping power. 
While the exact mechanism is not clear, Dr. Arthur J. Hartz speculated that nicotine or carbon 
monoxide in the smoke somehow poisons the heart and leads to heart failure. 


KAAIRDIYOWMAYAASPAXTHIY. AY /HAED NEH1VER /HER4D AXV IHT BIXFOHSR, 
BAHT DHEHSR IHT WAHZ - LIH4STIXD AEZ (DHAX FOHSRM AXV /HAASRT DI- 
HZIY5Z) DHAET FEH4LD (NAAT WAHSN OHR TUWS) - BAHT (AO7L THRIYS AXV 
DHAX AASRTAXFIHSHUL /HAASRTQ RIXSIHSPIYINTS). (AH LIHSTUL RIXSERSCH) 
PROHDUWSST (SAHM IHSNTRIHSTIHNX RIXZAHSLTS). AHKOHSRDIHNX TUW 
(AEN AASRTIHKUL IHN DHAX NOWVEHSMBER EY2TH NAYSNTIYNEYTIYFOHIR 
NUW IYSNXGLIND JERSNUL AXV MEHSDIXSIN), (SIHSGEREHT SMOWSKIHNX) 
KAO4ZIHZ (DHIHS LIYSTHUL DIHZIYSZ) DHAET WIY4KINZ (DHAX /HAASRTS 
PAH4MPIHNX PAW2ER). WAYL (DHIY IHGZAESKT MEHSKINIXZUM) IHZ NAAT KLIY5R, 
DAASKTER AASRTHER JEY2 /HAARTS SPEHSKYULEYTIHD DHAET NIHSKAXTIYN, 
OHR KAASRBIN MUNAASKSAYD IHN DHAX SMOWSK - SAHSM/HAW1 POY4ZINZ 
DHAX /HAASRT, AEND LIY4DZ TUW (/HAASRT FEYSLYER). 


CONCLUDING REMARKS 


This guide should get you off to a good start in phonetic writing for Narrator. The only way to get 
really proficient is to practice. Many people become good at it in as little as one day. Others make 
continual mistakes because they find it hard to let go of the rules of English spelling, so trust your 
ears. 


A More Technical Explanation 


The narrator speech synthesizer is a computer model of the human speech production process. It 
attempts to produce accurately spoken utterances of any English sentence, given only a phonetic 
representation as input. Another program in the Amiga speech system, the translator device, 
derives the required phonetic spelling from English text. Timing and pitch contours are produced 
automatically by the synthesizer software. 


In humans, the physical act of producing speech sounds begins in the lungs. To create a voiced 
sound, the lungs force air through the vocal folds (commonly called the vocal cords), which are held 
under tension and which periodically interrupt the flow of air, thus creating a buzz-like sound. This 
buzz, which has a spectrum rich in harmonics, then passes through the vocal tract and out the lips 
and nose, which alters its spectrum drastically. This is because the vocal tract acts as a frequency 


Narrator Device 149 


filter, selectively reinforcing some harmonics and suppressing others. It is this filtering that gives a 
speech sound its identity. The amplitude versus frequency graph of the filtering action is called the 
vocal tract transfer function. Changing the shape of the throat, tongue, and mouth retunes the filter 
system to accentuate different frequencies. 


The sound travels as a pressure wave through the air, and it causes the listener’s eardrum to vibrate. 
The ear and brain of the listener decode the incoming frequency pattem. From this the listener 
can subconsciously make a judgement about what physical actions were performed by the speaker 
to make the sound. Thus the speech chain is completed, the speaker having encoded his physical 
actions on a buzz via selective filtering and the listener having tumed the sound into guesses about 
physical actions by frequency decoding. 


Now that we know how humans produce speech, how does the Amiga do it? It tums out that 
the vocal tract transfer function is not random, but tends to accentuate energy in narrow bands 
called formants. The formant positions move fairly smoothly as we speak, and it is the formant 
frequencies to which our ears are sensitive. So, luckily, we do not have to model throat, tongue, 
teeth and lips with our computer, we can imitate formant actions instead. 


A good representation of speech requires up to five formants, but only the lowest three are required 
for intelligibility. The pre-V37 Narrator had only three formants, while the V37 Narrator has five 
formants for a more natural sounding voice. We begin with an oscillator that produces a waveform 
similar to that which is produced by the vocal folds, and we pass it through a series of resonators, 
each tuned to a different formant frequency. By controlling the volume and pitch of the oscillator 
and the frequencies of the resonators, we can produce highly intelligible and natural-sounding 
speech. Of course the better the model the better the speech; but more importantly, experience has 
shown that the better the control of the model’s parameters, the better the speech. 


Oscillators, volume controls, and resonators can all be simulated mathematically in software, and 
it is by this method that the narrator system operates. The input phonetic string is converted into a 
series of target values for the various parameters. A system of rules then operates on the string to 
determine things such as the duration of each phoneme and the pitch contour. Transitions between 
target values are created and smoothed to produce natural, continuous changes from one sound to 
the next. 


New values are computed for each parameter for every 8 milliseconds of speech, which produces 
about 120 acoustic changes per second. These values drive a mathematical model of the speech 
synthesizer. The accuracy of this simulation is quite good. Human speech has more formants that 
the narrator model, but they are high in frequency and low in energy content. 


The human speech production mechanism is a complex and wonderful thing. The more we learn 
about it, the better we can make our computer simulations. Meanwhile, we can use synthetic speech 
as yet another computer output device to enhance the man/machine dialogue. 


150 Amiga ROM Kernel Reference Manual: Devices 


Example Speech and Mouth Movement Program 


/* 

* Full Narrator.c 

* 

* This example program sends a string of phonetic text to the narrator 
* device and, while it is speaking, highlights, word-by-word, a 

* corresponding English string. In addition, mouth movements are drawn 
* in a separate window. 

* 

* Compile with SAS C 5.10 lc ~bl -cfistq -v -y -L 

* 

* Requires Kickstart V37 or greater. 

*/ 


#include <exec/types-h> 

#include <exec/memory.h> 
#include <dos/dos.h> 

#include <intuition/intuition.h> 
#include <ctype.h> 

#include <exec/exec.h> 

#include <fentl.h> 

#include <devices/narrator.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/intuition_protos.h> 
#include <clib/graphics protos.h> 
#include <clib/dos_protos.h> 


#finclude <stdlib.h> 
#include <string.h> 
#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 

/* 


* Due to an omission, the sync field defines were not included in older 
* versions of the narrator device include files. So, if they haven’t 
* already been defined, do so now. 


*/ 

#ifndef NDF_READMOUTH /* Already defined ? */ 
#define NDF_READMOUTH 0x01 /* No, define here */ 
#define NDF _READWORD 0x02 

#define NDF _READSYL 0x04 

#endif 


#define PEN3 
#define PEN2 
#define PEN1 
#define PENO 


/* Drawing pens */ 


OrPNW 


BOOL FromCLI = TRUE; 
BYTE chans[4] = {3, 5, 10, 12}; 


LONG EyesLeft; /* Left edge of left eye */ 
LONG EyesTop; /* Top of eyes box */ 
LONG EyesBottom; /* Bottom of eyes box */ 
LONG YMouthCenter; /* Pixels from top edge */ 
LONG XMouthCenter; /* Pixels from left edge */ 
LONG LipWidth, LipHeight; /* Width and height of mouth */ 


struct TextAttr MyFont = {"topaz.font", TOPAZ SIXTY, FS_NORMAL, FPF_ROMFONT, }; 


struct IntuitionBase *IntuitionBase = NULL; 
struct GfxBase *GfxBase = NULL; 


Narrator Device 151 


struct MsgPort *VoicePort = NULL; 
struct MsgPort *MouthPort = NULL; 
struct narrator rb *VoicelO = NULL; 
struct mouth rb *MouthIO = NULL; 


struct IntuiText HighLight; 
struct NewWindow NewWindow; 
struct Window *TextWindow; 
struct Window *FaceWindow; 
struct RastPort *FaceRast; 


void main(int argc, char **argv) 
{ 


LONG i; 

LONG sentence; 
LONG Offset; 
LONG CharsLeft; 
LONG ScreenPos; 
LONG WordLength; 
LONG LineNum; 


UBYTE *Tempptr; 
UBYTE *English; 
UBYTE *OldEnglish; 


UBYTE c; 

UBYTE *PhonPtr; /* Pointer to phonetic text x/ 
LONG PhonSize; /* Size of phonetic text */ 
UBYTE *PhonStart [100]; /* Start of phonetic sentences */ 
LONG NumPhonStarts; /* Number of phonetic sentences */ 
UBYTE *EngPtr; /* Pointer to English text UA 
LONG EngSize; /* Size of English text */ 
UBYTE *EngStart (100); /* Start of English sentences */ 
LONG NumEngStarts; /* Number of English sentences */ 
UBYTE *EngLine[24}; /* Start of line on screen */ 
LONG EngBytes [24]; /* Bytes per line on screen */ 
LONG NumEngLines; /* Number of lines on screen */ 


extern void Cleanup(UBYTE *errmsg) ; 

extern void ClearWindow(struct Window *TextWindow) ; 
extern void DrawFace(void); 

extern void UpdateFace (void); 


* (0) Note whether the program was started from the CLI or from 
* Workbench. 


*/ 
if (arge == 0) 
FromCLI = FALSE; 

/* 

* (1) Setup the phonetic text to be spoken. If there are any non- 

* alphabetic characters in the text (such as NEWLINES or TABS) 

* replace them with spaces. Then break up the text into sentences, 
* storing the start of each sentence in PhonStart array elements. 
*/ 


PhonPtr = "KAALRDIYOWMAYAASPAXTHIY. AY /HAED NEH1VER /HER4D AXV IHT " 
“BIXFOHSR, BAHT DHEHSR IHT WAHZ - LIH4STIXD AEZ (DHAX FOHSRM " 
“AXV /HAASRT DIHZIY5Z) DHAET FEH4LD (NAAT WAH5N OHR TUWS) - " 
"BAHT (AO7L THRIYS AXV DHAX AASRTAXFIHSHUL /HAASRTQ " 
“RIXSIHSPIYINTS). (AH LIHSTUL RIXSER5CH) PROHDUWSST (SAHM " 
“IHSNTRIHSTIHNX RIXZAHSLTS). AHKOHSRDIHNX TUW (AEN AASRTIHKUL " 
“IHN DHAX NOWVEHSMBER EY2THOX NAYSNTIYNEYTIYFOHIR NUW IYS5NXGLIND " 
“JERSNUL AXV MEHSDIXSIN), (SIHSGEREHT SMOWSKIHNX) KAO4ZIHZ " 
"(DHIHS LIYSTHUL DIHZIY5Z) DHAET WIY4KINZ (DHAX /HAASRTS " 
“PAH4MPIHNX PAW2ER). WAYL (DHIY IHGZAESKT MEHSKINIXZUM) IHZ " 
“NAAT KLIY5R, DAASKTER AASRTHER JEY2 /HAARTS SPEHSKYULEYTIHD " 
"DHAET NIH4KAXTIY2N- OHR KAASRBIN MUNAASKSAYD IHN DHAX SMOW5K- " 
“SAHSM/HAW1 POY4ZINZ DHAX /HAASRT, AEND LIY4D2 TUW (/HAASRT " 
“FEYSLYER) ."; 


152 Amiga ROM Kernel Reference Manual: Devices 


PhonSize = strlen(PhonPtr) ; 
NumPhonStarts = 0; 

PhonStart [NumPhonStarts++] = PhonPtr; 
for (i = 0; i < PhonSize; ++i) 


{ 

if (isspace((int) (c = *PhonPtr++))) 
*(PhonPtr-1) = ' '3 

if ue ==.) I] (c == 12?7)) 


*PhonPtr = '\0'; 
PhonStart [NumPhonStartst+] = ++PhonPtr; 
} 


/* 

* (2) Create the English text corresponding to the phonetic text above. 
* As before, insure that there are no TABS or NEWLINES in the text. 
* Break the text up into sentences and store the start of each 

* sentence in EngStart array elements. 

*/ 


EngPtr = "Cardiomyopathy. I had never heard of it before, but there it was " 
"listed as the form of heart disease that felled not one or two but " 
"all three of the artificial heart recipients. A little research " 
“produced some interesting results. According to an article in the " 
"November 8, 1984, New England Journal of Medicine, cigarette smoking " 
"causes this lethal disease that weakens the heart’s pumping power. we 
"While the exact mechanism is not clear, Doctor Arthur J Hartz " 
“speculated that nicotine or carbon monoxide in the smoke somehow " 
"poisons the heart and leads to heart failure."; 


EngSize = strlen(EngPtr); 
NumEngStarts = 0; 
EngStart [NumEngStarts++] = EngPtr; 
for (i = 0; i < EngSize; ++i) 

{ 


if (isspace((int) (c = *EngPtr++))) 
*(EngPtr-1) = ' '; 
if ig == '.') II (c == '?")) 


*EngPtr = ’\0'; 
EngStart [NumEngStartst++] = ++EngPtr; 
} 


/* 
* (3) Open Intuition and Graphics libraries. 
*/ 


if (! (IntuitionBase=(struct IntuitionBase *)OpenLibrary ("intuition.library", 0) )) 
Cleanup ("can’t open intuition") ; 


if ((GfxBase=(struct GfxBase *)OpenLibrary ("graphics.library", 0)) == NULL) 
Cleanup("can’t open graphics"); 
/* 
* (4) Setup the NewWindow structure for the text display and 
* open the text window. 
*/ 
NewWindow.LeftEdge = 20; 
NewWindow. TopEdge = 100; 
NewWindow.Width = 600; 
NewWindow.Height = 80; 
NewWindow.DetailPen = 0; 
NewWindow.BlockPen = 1; 
NewWindow.Title = " Narrator Demo "; 
NewWindow.Flags = SMART_REFRESH | ACTIVATE | WINDOWDEPTH | WINDOWDRAG; 
NewWindow.IDCMPFlags = NULL; 
NewWindow. Type = WBENCHSCREEN; 
NewWindow.FirstGadget = NULL; 
NewWindow.CheckMark = NULL; 
NewWindow.Screen = NULL; 
NewWindow.BitMap = NULL; 
NewWindow.MinWidth = 600; 
NewWindow.MinHeight = 80; 
NewWindow.MaxWidth = 600; 
NewWindow.MaxHeight = 80; 


Narrator Device 153 


if ((TextWindow = (struct Window *)OpenWindow (&NewWindow)) == NULL) 
Cleanup("Text window could not be opened"); 

/* 
* (4) Setup the NewWindow structure for the face display, open the 
* window, cache the RastPort pointer, and draw the initial face. 
*/ 

NewWindow. LeftEdge = 20; 

NewWindow. TopEdge = 12; 

NewWindow.Width = 120; 

NewWindow. Height = 80; 

NewWindow.DetailPen = 0; 

NewWindow.BlockPen = 1; 

NewWindow.Title = " Face "; 

NewWindow.Flags = SMART REFRESH | WINDOWDEPTH | WINDOWDRAG; 

NewWindow.IDCMPFlags = NULL; 

NewWindow. Type = WBENCHSCREEN; 

NewWindow.FirstGadget = NULL; 

NewWindow.CheckMark = NULL; 

NewWindow. Screen = NULL; 

NewWindow.BitMap = NULL; 

NewWindow.MinWidth = 120; 

NewWindow.MinHeight = 80; 

NewWindow.MaxWidth = 120; 

NewWindow.MaxHeight = 80; 

if ((FaceWindow = (struct Window *) OpenWindow (&NewWindow)) == NULL) 


Cleanup ("Face window could not be opened"); 
FaceRast = FaceWindow->RPort; 


DrawFace(); 


/* 
* (5) Create read and write msg ports. 
*/ 
if ((MouthPort = CreatePort (NULL,0)) == NULL) 
Cleanup ("Can’t get read port"); 
if ((VoicePort = CreatePort (NULL,0)) == NULL) 
Cleanup("Can’t get write port"); 
/* 
* (6) Create read and write I/O request blocks. 
*/ 


if (!(MouthIO = (struct mouth_rb *) 
CreateExtI0(MouthPort, sizeof (struct mouth_rb)))) 
Cleanup("Can’t get read IORB"); 


if (!(VoiceIO = (struct narrator _rb *) 
CreateExtI0O(VoicePort, sizeof (struct narrator _rb)))) 
Cleanup("Can’t get write IORB"); 


/* 
* 
*S 

VoicelO->ch_masks &chans[0]; 

VoiceIO->nm_masks sizeof (chans); 


VoiceIl0->message.io Command = CMD WRITE; 
VoiceI0O->flags = NDF_NEWIORB; 


(7) Set up the write I/O request block and open the device. 


ued 


if (OpenDevice("narrator.device", 0, VoiceIO, 0) != NULL) 
Cleanup ("OpenDevice failed"); 


/* 
* 


2, 


(8) Set up the read I/O request block. 


MouthI0->voice.message.io Device = VoiceIlO->message.io Device; 
MouthI0O->voice.message.io Unit Voicel0->message.io Unit; 
Mouth10->voice.message.io Message.mn_ReplyPort = MouthPort; 
MouthI0->voice.message.io Command = CMD_READ; 


nou 


154 Amiga ROM Kernel Reference Manual: Devices 


/* 
* (9) Initialize highlighting IntuiText structure. 
*/ 
HighLight.FrontPen = 1; 
HighLight.BackPen = 0; 
HighLight.DrawMode = JAM1; 
HighLight.ITextFont = &MyFont; 
HighLight.NextText = NULL; 
/* 
* (10) For each sentence, put up the English text in BLACK. As 
Narrator says each word, highlight that word in BLUE. Also 
* continuously draw mouth shapes as Narrator speaks. 
*/ 
for (sentence = 0; sentence < NumPhonStarts; ++sentence) 


~ 
* 


/ 


* 


(11) Begin by breaking the English sentence up into lines of 
text in the window. EngLine is an array containing a 
pointer to the start of each English text line. 


% 


*/ 


English = EngStart[sentence] + strspn((UBYTE *)EngStart[sentence], " "); 
NumEngLines = 0; 

EngLine (NumEngLines++] = English; 

CharsLeft = strlen(English); 

while (CharsLeft > 51) 


{ 

for (Offset = 51; *(Englisht+Offset) != ' '; --Offset) ; 
EngBytes[NumEngLines-1] = Offset; 

English += Offset + 1; 

* (English-1) = '\0'; 

EngLine [NumEngLines++] = English; 


CharsLeft 


Offset + 1; 


} 
EngBytes([NumEngLines-1] = CharsLeft; 
/* 
* (12) Clear the window and draw in the unhighlighted English text. 
*/ 


ClearWindow (TextWindow) ; 
1: 


10; 
20: 


HighLight.FrontPen 
HighLight.LeftEdge 
HighLight.TopEdge 


for (i = 0; i < NumEngLines; ++i) 


{ 

HighLight.IText = EngLine[i]; 

PrintIText (TextWindow->RPort, &HighLight, 0, 0); 
HighLight.TopEdge += 10; 

} 


HighLight.TopEdge = 20; 
HighLight.FrontPen = 3; 
HighLight.IText = EngLine[0); 
/* 
* (13) Set up the write request with the address and length of 
* the phonetic text to be spoken. Also tell device to 
* generate mouth shape changes and word sync events. 
*/ 


PhonStart [sentence]; 

strlen (VoiceIO->message.io Data); 
NDF_NEWIORB | NDF_WORDSYNC; 

i; 


VoiceIO->message.io Data 
VoiceIO->message.io Length 
Voicel0->flags 
VoiceI0->mouths 


/* 

* (14) Send the write request to the device. This is an 

* asynchronous write, the device will return immediately. 
*/ 


SendIO(VoiceI0O) ; 


Narrator Device 155 


/* 
* (15) Initialize some variables. 

*/ 

ScreenPos = 0; 

LineNum = 0; 

English = EngLine[LineNum] ; 

OldEnglish = English; 

MouthI0->voice.message.io Error = 0; 

/* 

* (16) Issue synchronous read requests. For each request we 

* check the sync field to see if the read returned a mouth 

* shape change, a start of word sync event, or both. We 

- continue issuing read requests until we get a return code 

* of ND_NoWrite, which indicates that the write has finished. 
* 


/ 


for (DoIO(MouthIO) ;MouthI0O->voice.message.io_ Error != ND_NoWrite;DoIO(MouthI0O) ) 
{ 


/* 
* (17) If bit 1 of the sync field is on, this is a start 
* of word sync event. In that case we highlight the 
x next word. 

*/ 


if (MouthIO->sync & NDF_READWORD) 


{ 
if ((Tempptr = strchr(English, ' ’)) != NULL) 
{ 


English = Tempptr + 1; 
*(English-1) = '\0'; 
} 


PrintIText (TextWindow->RPort, &HighLight, 0, 0); 


WordLength = strlen(OldEnglish) + 1; 
HighLight.IText = English; 
OldEnglish = English; 
ScreenPos += WordLength; 
if (ScreenPos >= EngBytes[LineNun] ) 
{ 
HighLight.LeftEdge = 10; 
HighLight . TopEdge += 10; 
ScreenPos = 0; 
English = OldEnglish = EngLine[++LineNum] ; 
HighLight.IText = English; 
} 
else 


HighLight.LeftEdge += 10*WordLength; 


/* 
* (18) If bit 0 of the sync field is on, this is a mouth 
* shape change event. In that case we update the face. 
*/ 


if (MouthIO->sync & NDF_READMOUTH) 
UpdateFace (); 


/* 
* (19) The write has finished (return code from last read equals 
* ND_NoWrite). We must wait on the write I/O request to 
* remove it from the message port. 

*/ 


WaitIO(Voicel0); 


} 


/* 


156 Amiga ROM Kernel Reference Manual: Devices 


* (20) Program completed, cleanup and return. 
* 


Cleanup ("Normal completion") ; 


} 


void Cleanup(UBYTE *errmsg) 
{ 


/* 

* (1) Cleanup and go away. This routine does not return but EXITs. 
x Everything it does is pretty self explanatory. 

*/ 


if (FromCLI) 
printf ("%s\n\r", errmsg) ; 
if (TextWindow) 
CloseWindow (TextWindow) ; 
if (FaceWindow) 
CloseWindow (FaceWindow) ; 
if (VoiceIO && VoiceIO->message.io_ Device) 
CloseDevice (VoiceI0) ; 
if (VoiceI0O) 
DeleteExtI0(VoicelI0O) ; 
if (VoicePort) 
DeletePort (VoicePort) ; 
if (MouthIO) 
DeleteExtIO(MouthI0O) ; 
if (MouthPort) 
DeletePort (MouthPort) ; 
if (GfxBase) 
CloseLibrary (GfxBase) ; 
if (IntuitionBase) 
CloseLibrary (IntuitionBase) ; 


exit (RETURN_OK) 7 

} 

void ClearWindow(struct Window *TextWindow) 
{ 

LONG OldPen; 

/* 
* 


xh 


(1) Clears a window. 


OldPen = (LONG) TextWindow->RPort->FgPen; 
SetAPen (TextWindow->RPort, 0); 
SetDrMd (TextWindow->RPort, JAM1); 


RectFill (TextWindow->RPort, 3, 12, TextWindow->Width-3, TextWindow->Height-2); 


SetAPen (TextWindow->RPort, OldPen); 
} 


void DrawFace () 


{ 


/* 

* (1) Draws the initial face. The variables defined here are used in 
* UpdateFace() to redraw the mouth shape. 

*/ 


EyesLeft = 15; 
EyesTop = 20; 
EyesBottom = 35; 


XMouthCenter 
YMouthCenter 


FaceWindow->Width >> 1; 
FaceWindow->Height - 25; 


SetAPen (FaceWindow->RPort, PEN1); 


RectFill (FaceWindow->RPort, 3, 10, FaceWindow->Width-3, FaceWindow->Height-2) ; 


SetAPen (FaceWindow->RPort, PENO); 


Narrator Device 157 


RectFill (FaceWindow->RPort, EyesLeft, EyesTop, EyesLeft+25, EyesTop+15); 
RectFill (FaceWindow->RPort, EyesLeft+65, EyesTop, EyesLeft+90, EyesTopt15); 


SetAPen (PFaceWindow->RPort, PEN3); 

Move (FaceWindow->RPort, XMouthCenter-(FaceWindow->Width >> 3), YMouthCenter) ; 
Draw (FaceWindow->RPort, XMouthCentert+ (FaceWindow->Width >> 3), YMouthCenter) ; 
} 


void UpdateFace() 
{ 


/* 
* (1) Redraws mouth shape in response to a mouth shape change message 
- from the device. Its all pretty self explanatory. 

*/ 


WaitBOVP (&FaceWindow->WScreen->ViewPort) ; 
SetAPen(FaceRast, PEN1); 
RectFill (FaceRast, 3, EyesBottom, FaceWindow->Width-3, FaceWindow->Height-2) ; 


LipWidth 
LipHeight 


MouthI0O->width*3; 
MouthI0O->height*2/3; 


SetAPen (FaceRast, PEN3); 
Move (FaceRast, XMouthCenter - LipWidth, YMouthCenter) ; 


Draw (FaceRast, XMouthCenter , YMouthCenter - LipHeight); 
Draw(FaceRast, XMouthCenter + LipWidth, YMouthCenter) ; 
Draw (FaceRast, XMouthCenter, YMouthCenter + LipHeight); 


Draw(FaceRast, XMouthCenter - LipWidth, YMouthCenter); 
} 


Additional Information on the Narrator Device 


Additional programming information on the narrator device can be found in the include files and 
the Autodocs for the narrator device and the Autodocs for the translator library. All are contained 
in the Amiga ROM Kernel Reference Manual: Includes and Autodocs. 


Narrator Device Information 


INCLUDES devices/narrator.h 
devices/narrator.i 


AUTODOCS narrator.doc 
translator.doc 





158 Amiga ROM Kernel Reference Manual: Devices 


chapter nine 
PARALLEL DEVICE 


The parallel device provides a hardware-independent interface to the Amiga’s Centronics- 
compatible parallel port. The primary use of the Amiga parallel port is for output to printers, 
but with its extensions for bi-directional I/O, it can also be used for communication with digitizers 
and high-speed links with other computers. The parallel device is based on the conventions of Exec 
device I/O, with extensions for parameter setting and control. 


Parallel Device 159 


Parallel Device Commands and Functions 


Command 
CMD_FLUSH 
CMD_READ 
CMD_RESET 
CMD_START 
CMD_STOP 
CMD_WRITE 


PDCMD_QUERY 


Operation 


Purge all queued requests for the parallel device. Does not affect active 
requests. 

Read a stream of characters from the parallel port. The number of 
characters can be specified or a termination character(s) can be used. 
Reset the parallel port to its initialized state. All active and queued I/O 
requests will be aborted. 

Restart all paused I/O over the parallel port. Reactivates the handshak- 
ing sequence. 

Pause all active I/O over the parallel port. Deactivates the handshaking 
sequence. 

Write out a stream of characters to the parallel port. The number of 
characters can be specified or a NULL-terminated string can be sent. 
Retum the status of the parallel port lines and registers. 


PDCMD_SETPARAMS Set the parameters of the parallel port. 


Exec Functions as Used In This Chapter 


AbortIOQ 
BeginIO() 


CheckIO() 
CloseDevice() 
DoIOQ 
OpenDevice() 
SendIOQ 
WaitIOO 


Abort a command to the parallel device. If the command is in progress, 
it is stopped immediately. If it is queued, it is removed from the queue. 
Initiate a command and retum immediately (asynchronous request). 
This is used to minimize the amount of system overhead. 

Determine the current state of an I/O request. 

Relinquish use of the parallel device. All requests must be complete. 
Initiate a command and wait for completion (synchronous request). 
Obtain use of the parallel device. 

Initiate a command and retum immediately (asynchronous request). 
Wait for the completion of an asynchronous request. When the request 
is complete the message will be removed from your reply port. 


Exec Support Functions as Used in This Chapter 


CreateExtIO(Q 
CreatePort() 


DeleteExtIO() 
DeletePort() 


Create an extended I/O request structure of type IOExtPar. This 
structure will be used to communicate commands to the parallel device. 
Create a signal message port for reply messages from the parallel 
device. Exec will signal a task when a message arrives at the port. 
Delete an extended I/O request structure created by CreateExtIO(). 
Delete the message port created by CreatePort(). 


160 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The parallel device operates like the other Amiga devices. To use it, you must first open the parallel 
device, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
System Devices” chapter for general information on device usage. 


The I/O request used by the parallel device is called IOExtPar. 


struct IOExtPar 
{ 


struct IOStdReq I0Par; 


ULONG io PExtFlags; /* additional parallel flags */ 
UBYTE io Status; /* status of parallel port and registers */ 
UBYTE io ParFlags; /* parallel device flags */ 


struct IOPArray io_PTermArray; /* termination character array */ 


° 
, 


See the include file devices/parallel.h for the complete structure definition. 


OPENING THE PARALLEL DEVICE 


Three primary steps are required to open the parallel device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an extended I/O request structure of type IOExtPar using CreateExtIO(). 
CreateExtIO() will initialize the I/O request to point to your reply port. 


e Open the parallel device. Call OpenDevice(), passing the I/O request. 


struct MsgPort *ParallelMP; /* Pointer to reply port */ 
struct IOExtPar *ParallelIO; /* Pointer to I/O request */ 


if (ParallelMP=CreatePort (0,0) ) 
if (ParallelIO=(struct IOExtPar *) 
CreateExtI0O(ParallelMP, sizeof (struct IOExtPar)) ) 
if (OpenDevice (PARALLELNAME, OL, (struct IORequest *)ParallelIO,0) ) 
printf("%s did not open\n", PARALLELNAME) ; 


During the open, the parallel device pays attention to just one flag; PARF_SHARED. For consis- 
tency, the other flag bits should also be properly set. Full descriptions of all flags will be given later. 
When the parallel device is opened, it fills the latest default parameter settings into the IOExtPar 
block. 


Parallel Device 161 


READING FROM THE PARALLEL DEVICE 


You read from the parallel device by passing an IOExtPar to the device with CMD_READ set in 
io_Command, the number of bytes to be read set in io_Length and the address of the read buffer 
set in io_Data. 


#define READ BUFFER SIZE 256 
char ParallelReadBuffer[READ BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ 


ParallelIO->I0Par.io Length ed 
ParallelIO->I0Par.io Data (APTR) &ParallelReadBuffer([0]; 
ParallelI0O->I10Par.io Command CMD_READ; 

DoIO((struct IORequest *)ParallelIO); 


READ_BUFFER_SIZE; 


oud 


If you use this example, your task will be put to sleep waiting until the parallel device reads 256 
bytes (or terminates early). Early termination can be caused by error conditions. 


WRITING TO THE PARALLEL DEVICE 


You write to the parallel device by passing an IOExtPar to the device with CMD_WRITE set in 
io_Command, the number of bytes to be written set in io_Length and the address of the write 
buffer set in io_Data. 


To write a NULL-terminated string, set the length to -1; the device will output from your buffer 
until it encounters and transmits a value of zero (0x00). 


ParallelIO->I0Par.io Length = -1; 

ParallelIO->I10Par.io Data = (APTR)"Parallel lines cross 7 times... "; 
ParallelIO->I0Par.io Command = CMD WRITE; 

DolO((struct IORequest *)ParallelIO); /* execute write */ 


The length of the request is -1, meaning we are writing a NULL-terminated string. The number of 
characters sent can be found in io_Actual. 


CLOSING THE PARALLEL DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). When the last close is 
performed, the device will deallocate all resources and buffers. The latest parameter settings will 
be saved for the next open. 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIO(Q: 
if (!(CheckIO(ParallelI0) )) 

{ 

AbortIO(ParallelIO); /* Ask device to abort request, if pending */ 


} 
WaitIO(ParallelIo); /* Wait for abort, then clean up */ 
CloseDevice((struct IORequest *)ParallelIO); 


162 Amiga ROM Kernel Reference Manual: Devices 


Ending A Read or Write with Termination Characters 


Reads and writes from the parallel device may terminate early if an error occurs or if an end-of-file 
is sensed. For example, if a break is detected on the line, any current read request will be retuned 
with the error ParErr_DetectedBreak. The count of characters read to that point will be in the 
io_Actual field of the request. 


You can specify a set of possible end-of-file characters that the parallel device is to look for in the 
input or output stream using the PDCMD_SETPARAMS command. These are contained in an 
io_PTermArray that you provide. io_PTermArray is used only when the PARF_EOFMODE flag 
is selected (see “Parallel Flags” below). 


If EOF mode is selected, each input data character read into or written from the user’s data block 
is compared against those in io_PTermArray. If a match is found, the IOExtPar is terminated as 
complete, and the count of characters transferred (including the termination character) is stored in 
io_Actual. 


To keep this search overhead as efficient as possible, the parallel device requires that the array of 
characters be in descending order. The array has eight bytes and all must be valid (that is, do not 
pad with zeros unless zero is a valid EOF character). Fill to the end of the array with the lowest 
value termination character. When making an arbitrary choice of EOF character(s), you will get the 
quickest response from the lowest value(s) available. 


/ 
Terminate Parallel.c 


This is an example of using a termination array for writes from the parallel 
device. A termination array is set up for the characters Q, E, A and %. The 
EOFMODE flag is set in io ParFlags to indicate that we want to use a 
termination array by sending the PDCMD SETPARAMS command to the device. 
Then, a CMD_WRITE command is sent to the device with io Length set to -1. 


The write will terminate when one of the four characters in the 
termination array is sent or when the end of the write buffer has been reached. 


Compile with SAS C 5.10 lc -bl -cfistq -v -y -L 


Run from CLI only 
/ 


% oe Ot OE OO OO OO 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 

#include <devices/parallel.h> 


#include <clib/exec_protos.h> 
#include <clib/alib_protos.h> 


#include <stdio.h> 

#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 

void main(void) 


struct MsgPort *ParallelMP; /* Define storage for one pointer */ 
struct IOExtPar *ParallelIO; /* Define storage for one pointer */ 


struct IOPArray Terminators = 
{ 
0x51454125, /* QEAA */ 


0x25252525 /* fill to end with lowest value, must be in descending order */ 
Me 


Parallel Device 163 


UBYTE *WriteBuffer ="abcdefghi jklmEopqrstuvwxyze"; 
UWORD ctr; 


if (ParallelMP=CreatePort (0,0) ) 


{ 
if (ParallelIO=(struct IOExtPar *) 
CreateExtIO(ParallelMP, sizeof (struct IOExtPar)) ) 


{ 
if (OpenDevice (PARALLELNAME, OL, (struct IORequest *)ParallelI0O,0) ) 
printf("%s did not open\n", PARALLELNAME) ; 
else 
{ 
/* Tell user what we are doing */ 
printf ("\fLooking for Q, E, A or % in output\n"); 


/* Set EOF mode flag 

* Set the termination array 

* Send PDCMD_SETPARAMS to the parallel device 

*/ 
ParallelIO->io ParFlags |= PARF_EOFMODE; 
ParallelIO->io PTermArray = Terminators; 
ParallelIO->I0Par.io Command = PDCMD_SETPARAMS; 

if (DoIO((struct IORequest *)ParallelIO) ) 

printf("Set Params failed "); /* Inform user of error */ 

else 


{ 
/* Send buffer */ 


ParallelI0O->10Par.io Length = =D? 
ParallelIO->I0Par.io Data = WriteBuffer; 
ParallelIO->I10Par.io Command = CMD_WRITE; 


if (DoIO((struct IORequest *)ParallelI0O)) 
printf("Error: Write failed\n"); 
else 
{ 
/* Display all characters sent */ 
printf("\nThese characters were sent:\n\t\t\tASCII\tHEX\n"); 
for (ctr=0;ctr<ParallelIO->10Par.io Actual;ctr+t+) 
printf ("\t\t\ttc\ttx\n", *WriteBuffer, *WriteBuffert++); 
printf("\nThe actual number of characters sent: %d\n", 
ParallelIO->I10Par.io Actual); 
} 
} 


CloseDevice((struct I0Request *)ParallelI0O); 


DeleteExtIO((struct IORequest *)ParallelIO); 
} 


else 
printf("Error: Could not create I/O request\n"); 


DeletePort (ParallelMP) ; 
} 


else 
printf("Error: Could not create message port\n"); 


The read will terminate before the io_Length number of characters is read if a ‘Q’, ‘E’, or ‘A’ is 


detected. 


It's Usually For Output. Most applications for the parallel device use the device for 


output, hence the termination feature is usually done on the output stream. 


164 Amiga ROM Kernel Reference Manual: Devices 


Setting Parallel Parameters 


You can control the parallel parameters shown in the following table. The parameter name within 
the parallel IOExtPar data structure is shown below. All of the fields described in this section are 
filled with defaults when you call OpenDevice(). Thus, you need not worry about any parameter 
that you do not need to change. The parameters are defined in the include file devices/parallel.h. 


Parallel Parameters (IOExtPar) 


IOExtPar 
Field Name Parallel Device Parameter It Controls 
io_PExtFlags Reserved for future use. 


io_PTermArray A byte-array of eight termination characters, must be in descending 
order. If EOFMODE is set in the parallel flags, this array specifies 
eight possible choices of characters to use as an end-of-file mark. 
See the section above titled “Ending A Read Or Write with Termi- 
nation Characters” and the PDCMD_SETPARAMS summary page 


in the Autodocs. 

io_Status Contains status information. It is filled in by the PDCMD_QUERY 
command. 

io_ParFlags See “Parallel Flags” below. 


You set the parallel parameters by passing an IOExtPar to the device with PXDCMD_SETPARAMS 
set in io_Command and with the flags and parameters set to the values you want. 


ParallelI0O->io ParFlags & 

ParallelI0O->I10Par.io Command 

if (DoIO(ParallelI0); 
printf("Error setting parameters! \n"); 


“PARF_EOFMODE; /* Set EOF mode */ 
PDCMD_SETPARAMS; /* Set params command */ 


The above code fragment modifies one bit in io_ParFlags, then sends the command. 


Proper Time for Parameter Changes. A parameter change should not be performed 
while an I/O request is actually being processed, because it might invalidate already active 
request handling. Therefore you should use PPCMD_SETPARAMS only when you have 
no parallel I/O requests pending. 


Parallel Device 165 


PARALLEL FLAGS (bit definitions for io_ParFlags) 


The flags shown in the following table can be set to affect the operation of the parallel device. 
Note that the default state of all of these flags is zero. The flags are defined in the include file 
devices/parallel.h. 

Parallel Flags (io_ParFlags) 


Flag Name Effect on Device Operation 


PARF_EOFMODE Set this bit if you want the parallel device to check I/O characters 
against io_TermArray and terminate the I/O request immediately 
if an end-of-file character has been encountered. Note: This bit can 
be set and reset directly in the user’s [OExtPar block without a call 
to PDCMD_SETPARAMS. 

PARF_ACKMODE Set this bit if you want to use ACK handshaking. 

PARF_FASTMODE Set this bit if you want to use high-speed mode for transfers to 
high-speed printers. This mode will send out data as long as the 
BUSY signal is low. The printer must be able to raise the BUSY 
signal within three microseconds or data will be lost. Should only 
be used when the device has been opened for exclusive-access. 

PARF_SLOWMODE Set this bit if you want to use slow-speed mode for transfers to very 
slow printers. Should not be used with high-speed printers. 

PARF_SHARED Set this bit if you want to allow other tasks to simultaneously access 
the parallel port. The default is exclusive access. If someone 
already has the port, whether for exclusive or shared access, and 
you ask for exclusive access, your OpenDevice() call will fail (must 
be modified before OpenDevice(Q)). 


Querying the Parallel Device 


You query the parallel device by passing an IOExtPar to the device with PDCMD_QUERY set 
in io_Command. The parallel device will respond with the status of the parallel port lines and 
registers. 

UWORD Parallel Status; 


ParallelI0O->IOPar.io Command = PDCMD QUERY; /* indicate query */ 
DoIO((struct IO0Request *)ParallelIO); 
Parallel Status = ParallelIO->io_ Status; /* store returned status */ 


The 8 status bits of the parallel device are returned in io_Status. 


166 Amiga ROM Kernel Reference Manual: Devices 


Parallel Device Status Bits 


Function 


Printer busy toggle (offline) 
Paper out 
Printer Select on the A1000. On the A500 and A2000, select 


is also connected to to the parallel port’s Ring Indicator. Be 
cautious when making cables. 

read=0; write=1 

(reserved) 





The parallel device also retums error codes whenever an operation is attempted. 


struct IOPArray Terminators = 


{ 
0x51454141, /‘* QEAA */ 


0x41414141 /* fill to end with lowest value, must be in descending order */ 

he 

ParallellIO->io ParFlags != PARF_EOFMODE; /* Set EOF mode flag */ 
ParallelIO->io PTermArray = Terminators; /* Set termination characters */ 


ParallellIO->I10Par.io Command = PDCMD_SETPARAMS; /* Set parameters */ 
if (DoIO((struct IORequest *)ParallelIO)) 
printf("Set Params failed. Error: %d ",ParallelIO->IOPar.io Error); 


The error is returned in the io_Error field of the IOExtPar structure. 


Parallel Device Error Codes 
Error Explanation 


ParErr_DevBusy Device in use 
ParErr_BufToBig Out of memory 
ParErr_InvParam Invalid parameter 


ParErr_LineErr Parallel line error 
ParErr_NotOpen Device not open 
ParErr_PortReset Port Reset 
ParErr_InitErr Initialization Error 





~ 


OO OO 


Parallel.c 
Parallel device example 
Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/io.h> 

#include <exec/memory.h> 
#include <dos/dos.h> 

#include <devices/parallel.h> 


Parallel Device 167 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#endif 


void main (void) 


struct MsgPort *ParallelMP; /* Define storage for one pointer */ 
struct IOExtPar *ParallelI0O; /* Define storage for one pointer */ 
ULONG WaitMask; /* Collect all signals here x/ 
ULONG Temp; /* Hey, we all need pockets :-) */ 


if (ParallelMP=CreatePort (0,0) ) 
{ 


if (ParallelIO=(struct IOExtPar *) 
CreateExtIO(ParallelMP, sizeof (struct IOExtPar)) ) 
{ 


if (OpenDevice (PARALLELNAME, OL, (struct IORequest *)ParallelIO,0) ) 
printf ("%s did not open\n", PARALLELNAME) ; 

else 
{ 
/* Precalculate a wait mask for the CTRL-C, CTRL-F and message port 

* signals. When one or more signals are received, Wait() will 

* return. Press CTRL-C to exit the example. Press CTRL-F to 

* wake up the example without doing anything. NOTE: A signal 

* may show up without an associated message! 

ey 

WaitMask = SIGBREAKF_CTRL C | SIGBREAKF_CTRL F | 

1L << ParallelMP->mp_SigBit; 


ParallelIO->10Par.io Command 
ParallelIO->I0Par.io Length -1; 
ParallelIO->10Par.io Data (APTR) "Hey, Jude!\\r\n"; 
SendIO(ParallelIO); /* execute write */ 


CMD_WRITE; 


printf ("Sleeping until CTRL-C, CTRL-F, or write finish\n"); 
while (1) 

{ 

Temp = Wait (WaitMask); 

printf ("Just woke up (YAWN!) \n"); 


if (SIGBREAKF_ CTRL _C & Temp) 
break; 


if (CheckIO(ParallelIO) ) /* If request is complete... */ 
{ 
WaitIO(ParallelIO); /* clean up and remove reply */ 
printf ("%ld bytes sent\n",ParallelI0O->I10Par.io Actual); 
break; 
} 

} 


AbortIO(ParallelIO); /* Ask device to abort request, if pending */ 
WaitIO(ParallelIO); /* Wait for abort, then clean up */ 


CloseDevice((struct IORequest *)ParallelI0O); 
} 
DeleteExtIO(ParallelIO); 


} 
DeletePort (ParallelMP) ; 
} 


168 Amiga ROM Kernel Reference Manual: Devices 


Additional Information on the Parallel Device 


Additional programming information on the parallel device can be found i> the include files and the 
Autodocs for the parallel device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Parallel Device Information 


INCLUDES devices/parallel.h 


devices/parallel.i 
AUTODOCS parallel.doc 





Parallel Device 169 


chapter ten 
PRINTER DEVICE 


The printer device offers a way of sending configuration-independent output to a printer attached to 
the Amiga. It can be thought of as a filter: it takes standard commands as input and translates them 
into commands understood by the printer. The commands sent to the printer are defined in a specific 
printer driver program. For each type of printer in use, a driver (or the driver of a compatible 
printer) should be present in the devs:printers directory. 


Printer Driver Source Code In This Chapter 


EpsonX A YMCB, 8 pin, multi-density interleaved printer. 


HP_LaserJet A black and white, multi-density, page-oriented printer. 





Printer Device 171 


Printer Device Commands and Functions 


Command 
CMD_FLUSH 
CMD_RESET 


CMD_START 
CMD_STOP 
CMD_WRITE 


PRD_DUMPRPORT 
PRD_PRTCOMMAND 
PRD_QUERY 
PRD_RAWWRITE 


Operation 


Remove all queued requests for the printer device. Does not affect 
active requests. 

Reset the printer device to its initialized state. All active and 
queued I/O requests will be aborted. 

Restart all paused I/O requests 

Pause all active and queued I/O requests. 

Write out a stream of characters to the printer device. The number 
of characters can be specified or a NULL-terminated string can 
be sent. 

Dump the specified RastPort to a graphics printer. 

Send a command to the printer. 

Retum the status of the printer port’s lines and registers. 

Send unprocessed output to the the printer. 


Exec Functions as Used In This Chapter 


AbortIO() 
CloseDevice() 


DoIOQ 
OpenDevice() 
SendIOQ 
WaitIOQ 


Abort a command to the printer device. 

Relinquish use of the printer device. All requests must be com- 
plete before closing. 

Start a command and wait for completion (synchronous request). 
Obtain use of the printer device. 

Start a command and retum immediately (asynchronous request). 
Wait for the completion of an asynchronous request. When the 
request is complete, the message will be removed from the printer 
message port. 


Exec Support Functions as Used in This Chapter 


CreatePort() 


CreateExtIO() 


DeletePort() 
DeleteExtIO(Q 


Create a signal message port for reply messages from the audio 
device. Exec will signal a task when a message arrives at the 
reply port. 

Create an I/O request structure of type printerIO. This structure 
will be used to send commands to the printer device. 

Delete the message port created by CreatePort(). 

Delete an I/O request structure created by CreateExtIO(Q. 


172 Amiga ROM Kernel Reference Manual: Devices 


Printer Device Access 


The printer device is totally transparent to an application. It uses information set up by the 
Workbench Preferences Printer and PrinterGfx tools to identify the type of printer connection 
(serial or parallel), type of dithering, etc. It also offers the flexibility to send raw information to 
the printer for special non-standard or unsupported features. Raw data transfer is not recommended 
for conventional text and graphics since it will result in applications that will only work with 
certain printers. By using the standard printer device interface, an application can perform device 
independent output to a printer. 


Don't Hog The Device. The printer device is currently an exclusive access device. Do 
Not tie it up needlessly. 


There are two ways of doing output to the printer device: 


e PRT:—the AmigaDOS printer device 
PRT: may be opened just like any other AmigaDOS file. You may send standard escape 
sequences to PRT: to specify the options you want as shown in the command table below. The 
escape sequences are interpreted by the printer driver, translated into printer-specific escape 
sequences and forwarded to the printer. When using PRT: the escape sequences and data must 
be sent as a character stream. Using PRT: is by far the easiest way of doing text output to a 
printer. 


e printer.device—to directly access the printer device itself 
By opening the printer device directly, you have full control over the printer. You can either 
send standard escape sequences as shown in the command table below or send raw characters 
directly to the printer with no processing at all. Doing this would be similar to sending raw 
characters to SER: or PAR: from AmigaDOS. (Since this interferes with device-independence 
it is strongly discouraged). Direct access to the printer device also allows you to transmit device 
I/O commands, such as reset and flush, and do a raster dump on a graphics-capable printer. 


Use A Stream to Escape. All “raw escape sequences” transmitted to the printer through 
the printer device must take the form of a character stream. 


OPENING PRT: 


When using the printer device as PRT:, you can open it just as though it were a normal AmigaDOS 
output file. 

struct FileHandle *file; 

file = Open( "PRT:", MODE NEWFILE ); /* Open PRT: */ 


if (file == 0) /* if the open was unsuccessful */ 
exit (PRINTER WONT OPEN); 


Printer Device 173 


WRITING TO PRT: 


Once you’ve opened it, you can print by calling the AmigaDOS Write() standard I/O routine. 
actual length = Write(file, dataLocation, length); 


where 


file 
is a file handle. 


dataLocation 
is a pointer to the first character in the output stream you wish to write. This stream can contain 
the standard escape sequences as shown in the command table below. The printer command 
aRAW (see the Printer Device Command Functions table below) can be used in the stream if 
character translation is not desired. 


length 
is the length of the output stream. 


actual_length 
is the actual length of the write. For the printer device, if there are no errors, this will be the 
same as the length of write requested. The only exception is if you specify a value of -1 for 
length. In this case, -1 for length means that a null (0) terminated stream is being written to 
the printer device. The device returns the count of characters written prior to encountering the 
null. If it returns a value of -1 in actual_length, there has been an error. 


-1 = STOP! Ifa -1 is retumed by Write(), do not do any additional printing. 


CLOSING PRT: 


When the printer I/O is complete, you should close PRT:. Don’t keep the device open when you are 
not using it. The user may have changed the printer settings by using the Workbench Preferences 
tool. There’s also the possibility the printer has been tumed off and on again causing the printer 
to switch to its own default settings. Every time the printer device is opened, it reads the current 
Preferences settings. Hence, by always opening the printer device just before printing and always 
closing it afterwards, you ensure that your application is using the current Preferences settings. 


Close (file); 
In DOS, You Must Be A Process. Printer I/O through the DOS must be done by a 
process, not by a task. DOS utilizes information in the process control block and would 


become confused if a simple task attempted to perform these activities. Printer I/O using 
the printer device directly, however, can be performed by a task. 


The remainder of this chapter will deal with using the printer device directly. 


174 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The printer device operates like the other Amiga devices. To use it, you must first open the printer 
device, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
Devices” chapter for general information on device usage. 


There are three distinct kinds of data structures required by the printer I/O routines. Some of the 
printer device I/O commands, such as CMD_START and CMD_WRITE require only an IOStdReq 
data structure. Others, such as PRD-_DUMPRPORT and PRD_PRTCOMMAND,, require an ex- 
tended data structure called IODRPReq (for “Dump a RastPort Request”) or IOPrt CmdReq (for 
“Printer Command Request’’). 


For convenience, it is strongly recommended that you define a single data structure called printerIO, 
that can be used to represent any of the three pre-defined printer communications request blocks. 


union printerIO 


struct I0StdReq ios; 
struct IODRPReq iodrp; 
struct IOPrtCmdReq iopc; 


he 


struct IODRPReq 
{ 


struct 
struct 
struct 
UWORD 
UBYTE 
BYTE 
struct 
struct 
ULONG 
UWORD 
UWORD 
UWORD 
UWORD 
LONG 
LONG 
UWORD 
he 


Message io_Message; 
Device *io Device; 
Unit *io Unit; 
io_Command; 

io Flags; 

io_Error; 

RastPort *io RastPort; 
ColorMap *io ColorMap; 
io Modes; 

io Srex; 

io SrcyY; 

io SrcWidth; 

io SrcHeight; 

io DestCols; 

io DestRows; 

io_ Special; 


struct IOPrtCmdReq 


struct 
struct 
struct 
UWORD 
UBYTE 
BYTE 
UWORD 
UBYTE 
UBYTE 
UBYTE 
UBYTE 


he 


Message io_Message; 
Device *io Device; 
Unit *io Unit; 
io_Command; 
io_Flags; 

io_Error; 

io _PrtCommand; 
io_Parm0; 

io_Parml; 

io _Parm2; 

io_Parm3; 


device node pointer */ 
unit (driver private) */ 
device command */ 


error or warning num */ 
raster port */ 

color map */ 

graphics viewport modes */ 
source x origin */ 
source y origin */ 
source x width */ 
source x height */ 
destination x width */ 
destination y height */ 
option flags */ 


device node pointer */ 
unit (driver private) */ 
device command */ 


error or warning num */ 
printer command */ 

first command parameter */ 
second command parameter */ 
third command parameter */ 
fourth command parameter */ 


See the include file exec/io.h for more information on IOStdReq and the include file devices/printer.h 
for more information on IODRPReq and IOPrtCmdReq. 


Printer Device 175 


OPENING THE PRINTER DEVICE 


Three primary steps are required to open the printer device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an extended I/O request structure of type printerIO with the CreateExtIO() function. 
This means that one memory area can be used to represent three distinct forms of memory 
layout for the three different types of data structures that must be used to pass commands to the 
printer device. By using CreateExtIO(), you automatically allocate enough memory to hold 
the largest structure in the union statement. 


e Open the printer device. Call OpenDevice(), passing the I/O request. 


union printerIO 


struct I0StdReq ios; 

struct IODRPReq iodrp; 

struct IOPrtCmdReq iopc; 
Me 


struct MsgPort *PrintMP; /* Message port pointer */ 
union printerIO *PrintI0; /* I/O request pointer */ 


if (PrintMP=CreateMsgPort() ) 
if (PrintIO=(union printerIO *) 
CreateExtIO(PrintMP, sizeof (union printerI0O)) ) 
if (OpenDevice ("printer.device", OL, (struct IORequest *)PrintIO,0) ) 
printf ("printer.device did not open\n"); 


The printer device automatically fills in default settings for all printer device parameters from 
Preferences. In addition, information about the printer itself is placed into the appropriate fields of 
printerIO. (See the “Obtaining Printer Specific Data” section below.) 


Pre-V36 Tasks and OpenDevice(). Tasks in pre-V36 versions of the operating system 
are not able to safely OpenDevice() the printer device because it may be necessary to 
load it in from disk, something only a process could do under pre-V36. V36 and higher 
versions of the operating system do not have such a limitation. 


WRITING TEXT TO THE PRINTER DEVICE 


Text written to a printer can be either processed text or unprocessed text. 


Processed text is written to the device using the CMD_WRITE command. The printer device 
accepts a character stream, translates any embedded escape sequences into the proper sequences 
for the printer being used and then sends it to the printer. The escape sequence translation is based 
on the printer driver selected either through Preferences or through your application. You may also 
send a NULL-terminated string as processed text. 


Unprocessed text is written to the device using the PRD-RAWWRITE command. The printer 
device accepts a character stream and sends it unchanged to the printer. This implies that you 
know the exact escape sequences required by the printer you are using. You may not send a 
NULL-terminated string as unprocessed text. 


176 Amiga ROM Kernel Reference Manual: Devices 


One additional point to keep in mind when using PRD_RAWWRITE is that Preference settings for 
the printer are ignored. Unless the printer has already been initialized by another command, the 
printer’s own default settings will be used when printing raw, not the user’s Preferences settings. 


You write processed text to the printer device by passing an IOStdReq to the device with 
CMD_WRITE set in io_Command, the number of bytes to be written set in io_Length and 
the address of the write buffer set in io_Data. 


To write a NULL-terminated string, set the length to -1; the device will output from your buffer 
until it encounters a value of zero (0x00). 


PrintI0O->ios.io Length 
PrintI0O->ios.io Data (APTR)"I went to a fight and a hockey game broke out." 
PrintI0O->ios.io Command CMD_WRITE; 

DoIO((struct IORequest *)PrintIO) ; 


-1; 


The length of the request is -1, meaning we are writing a NULL-terminated string. The number of 
characters sent will be found in io_Actual after the write request has completed. 


You write unprocessed text to the printer device by passing an IOStdReq to the device with 
PRD_RAWWRITE set in io_Command, the number of bytes to be written set in io_Length and 
the address of the write buffer set in io_Data. 


UBYTE *outbuffer; 


PrintI0O->ios.io Length = strlen(outbuffer); 
PrintI0O->ios.io Data = (APTR) outbuffer; 
PrintI0O->ios.io Command = PRD _RAWWRITE; 
DoIO((struct IORequest *)PrintIO); 


lOStdRegq Only. 1/O requests with CMD_WRITE and PRD_RAWWRITE must use the 
1OStdReq structure of the union printerIO. 


IMPORTANT POINTS ABOUT PRINT REQUESTS 


e Perform printer I/O from a separate task or process 
It is quite reasonable for a user to expect that printing will be performed as a background 
operation. You should try to accommodate this expectation as much as possible. 


e Give the user a chance to stop 
Your application should always allow the user to stop a print request before it is finished. 


e Don’t confuse aborting a print request with cancelling a page 
Some applications seem to offer the user the ability to abort a multi-page print request when 
in fact the abort is only for the current page being printed. This results in the next page being 
printed instead of the request being stopped. Do not do this! It only confuses the user and 
takes away from your application. There is nothing wrong with allowing the user to cancel a 
page and continue to the next page, but it should be explicit that this is the case. If you abort a 
print request, the entire request should be aborted. 


Printer Device 177 


CLOSING THE PRINTER DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIOQ. 


AbortIO(PrintI0O); /* Ask device to abort request, if pending */ 
WaitIO(PrintIO); /* Wait for abort, then clean up */ 


CloseDevice((struct IORequest *)PrintIO); 


Use AbortlO()/WaitlO() Intelligently. Only call Abort1O()/WaitIOQ for requests which 
have already been sent to the printer device. Using the AbortIO()/WaitIO(Q sequence on 
requests which have not been sent results in a hung condition. 


Sending Printer Commands to a Printer 


As mentioned before, it is possible to include printer commands (escape sequences) in the character 
stream and send them to the printer using the CMD_WRITE device I/O command. It is also 
possible to use the printer command names using the device I/O command PRD_PRTCOMMAND 
with the [OPrtCmdReq data structure. This gives you a mnemonic way of setting the printer to 
your program needs. 


You send printer commands to the device by passing an IOPrtCmdReq to the device with 
PRD_PRTCOMMAND set in io_Command, the printer command set in io_PrtCommand and up 
to four parameters set in Parm0 through Parm3. 


#include <devices/printer.h> 


PrintI0O->iopc.io PrtCommand = aSLRM; /* Set left & right margins */ 
PrintI0O->iopc.io Parm0 = 1; /* Set left margin = 1 
PrintI0O->iope.io Parml 19; /* Set right margin = 79 */ 
PrintIO->iopc.io Parm2 : 

PrintIO->iopc.io Parm3 0; 
PrintI0->iopc.io Command = PRD _PRTCOMMAND; 
DoIO((struct IORequest *)PrintIO); 


| | 
wun 


Consult the command function table listed below for other printer commands. 


PRINTER COMMAND DEFINITIONS 


The following table describes the supported printer functions. 


Just Because We Have It Doesn't Mean You Do. Not all printers support every 
command. Unsupported commands will either be ignored or simulated using available 
functions. 


To transmit a command to the printer device, you can either formulate a character stream con- 
taining the material shown in the “Escape Sequence” column of the table below or send an 
PRD_PRTCOMMAND device I/O command to the printer device with the “Name” of the function 
you wish to perform. 


178 Amiga ROM Kernel Reference Manual: Devices 


Name 
aRIS 


aIND 


aSGRO 
aSGR3 
aSGR23 
aSGR4 
aSGR24 
aSGR1 
aSGR22 
aSFC 


aSBC 


aSHORPO 
aSHORP2 
aSHORP1 
aSHORP4 
aSHORP3 
aSHORP6 
aSHORPS 
aDEN6 
aDENS 
aDEN4 
aDEN3 
aDEN2 
aDEN1 


aSUS2 
aSUS1 
aSUS4 
aSUS3 
aSUSO 
aPLU 

aPLD 


aFNT1 


Cmd 
No. 


OPOANANDN LhWNHK © 


13 


Printer Device Command Functions 


Escape 
Sequence 


ESCc 
ESC#1 


ESC[Om 
ESC[3m 
ESC[23m 
ESC[4m 
ESC[24m 
ESC[1m 
ESC[22m 
ESC[nm 


ESC[nm 


ESC[Ow 
ESC[2w 
ESC[1w 
ESC[4w 
ESC[3w 
ESC[6w 
ESC[S5w 
ESC[6"z 
ESC[5"z 
ESC[4"z 
ESC[3"z 
ESC[2"z 
ESC[1"z 


ESC[2v 
ESC[lv 
ESC[4v 
ESC[3v 
ESC[Ov 
ESCL 

ESCK 


ESC(B 
ESC(R 


Function 


Reset 

Initialize 
Linefeed 
Retum,linefeed 
Reverse linefeed 


Normal char set 

Italics on 

Italics off 

Underline on 

Underline off 

Boldface on 

Boldface off 

Set foreground color where n 
stands for a pair of ASCII digits, 
3 followed by any number 0-9 
(See ISOColor Table) 

Set background color where n 
stands for a pair of ASCII digits, 
4 followed by any number 0-9 
(See ISO Color Table) 

Normal pitch 

Elite on 

Elite off 

Condensed fine on 

Condensed off 

Enlarged on 

Enlarged off 

Shadow print on 

Shadow print off 

Doublestrike on 

Doublestrike off 

NLQ on 

NLQ off 


Superscript on 
Superscript off 
Subscript on 
Subscript off 
Normalize the line 
Partial line up 
Partial line down 


US char set or Typeface 0 
French char set or Typeface 1 


Defined 
by: 


ISO 
+++ 
ISO 
ISO 
ISO 


ISO 
ISO 
ISO 
ISO 
ISO 
ISO 
ISO 
ISO 


ISO 


DEC 
DEC 
DEC 
DEC 
DEC 
DEC 
DEC 
DEC (sort of) 
DEC 
DEC 
DEC 
DEC 
DEC 


+++ 
+++ 
+++ 
+++ 
+++ 
ISO 
Iso 


DEC 
DEC 


Printer Device 179 


aFNT2 
aFNT3 
aFNT4 
aFNTS 
aFNT6 
aFNT7 
aFNT8 
aFNT9 
aFNT10 


aPROP2 
aPROPI1 
aPROPO 
aTSS 
aJFY5 
aJFY7 
aJFY6 
aJFYO 
aJFY3 
aJFY1 


aVERPO 
aVERP1 
aSLPP 
aPERF 
aPERFO 


aLMS 
aRMS 
aTMS 
aBMS 
aSTBM 
aSLRM 
aCAM 


aHTS 
aVTS 
aTBCO 
aTBC3 
aTBCl 
aTBC4 
aTBCALL 
aTBSALL 
aEXTEND 


aRAW 


ESC(K 
ESC(A 
ESC(E 
ESC(H 
ESC(Y 
ESC(Z 
ESC 

ESC(6 

ESC(C 


ESC[2p 

ESC[1p 

ESC[Op 

ESC[n E 
ESC[5S F 
ESC[7 F 
ESC[6 F 
ESC(0 F 
ESC[3 F 
ESC[1 F 


ESC[0z 
ESC[1z 
ESC[nt 
ESC[nq 
ESC[0q 


ESC#9 
ESC#0 
ESC#8 
ESC#2 
ESC[n;nr 
ESC[n;ns 
ESC#3 


ESCH 
ESCJ 
ESC[0g 
ESC([3g 
ESC[1g 
ESC[4g 
ESC#4 
ESC#5 
ESC[n"x 


ESC[n"r 


German char set or Typeface 2 
UK char set or Typeface 3 
Danish I char set or Typeface 4 
Swedish char set or Typeface 5 
Italian char set or Typeface 6 
Spanish char set or Typeface 7 
Japanese char set or Typeface 8 
Norwegian char set or Typeface 9 
Danish II char set or Typeface 10 
(See Suggested Typefaces Table) 


Proportional on 
Proportional off 
Proportional clear 

Set proportional offset 
Auto left justify 

Auto right justify 
Auto full justify 

Auto justify off 

Letter space (justify) 
Word fill(auto center) 


1/8" line spacing 
1/6" line spacing 
Set form length n 
Perf skip n (n>0) 
Perf skip off 


Left margin set 

Right margin set 

Top margin set 

Bottom margin set 

Top and bottom margins 
Left and right margins 
Clear margins 


Set horizontal tab 
Set vertical tabs 
Clear horizontal tab 
Clear all h. tabs 
Clear vertical tab 
Clear all v. tabs 
Clear all h. & v. tabs 
Set default tabs 
Extended commands 


Next n chars are raw 


180 Amiga ROM Kernel Reference Manual: Devices 


DEC 
DEC 
DEC 
DEC 
DEC 
DEC 
+++ 

DEC 
+++ 


+++ 
+++ 
+++ 
ISO 
ISO 
ISO 
ISO 
ISO 
ISO (special) 
ISO (special) 


+++ 
+++ 
DEC 
+++ 
+++ 


+++ 
+++ 
+++ 
+++ 
DEC 
DEC 
+++ 


ISO 
ISO 
ISO 
ISO 
ISO 
ISO 
+++ 
+++ 
+++ 


+++ 


Legend: 

ISO indicates that the sequence has been defined by the International 
Standards Organization. This is also very similar to ANSI x3.64. 

DEC indicates a control sequence defined by Digital Equipment Corporation. 

+++ indicates a sequence unique to Amiga. 

n stands for a decimal number expressed as a set of ASCII digits. 
In the aRAW string ESC[S"rHELLO, n is substituted by 5, the 
number of RAW characters you send to the printer. 

ISO Color Table Suggested Typefaces 
0 Black 0 Default typeface 
1 Red 1 Line Printer or equivalent 
2 Green 2 Pica or equivalent 
3 Yellow 3 Elite or equivalent 
4 Blue 4 Helvetica or equivalent 
5 Magenta 5 Times Roman or equivalent 
6 Cyan 6 Gothic or equivalent 
7 White 7 Script or equivalent 
8 NC 8 Prestige or equivalent 
9 Default 9 Caslon or equivalent 
10 Orator or equivalent 


Obtaining Printer Specific Data 


Information about the printer in use can be obtained by reading the PrinterData and 
PrinterExtendedData structures. The values found in these structures are determined by the 
pr inter driver selected through Preferences. The data structures are defined in devices/prtbase.h. 


Printer specific data is retumed in printerIO when the printer device is opened. To read the 
structures, you must first set the PrinterData structure to point to iodrp.io_Device of the printerIO 
used to open the device and then set PrinterExtendedData to point to the extended data portion of 


PrinterData. 


/ 


Printer Data.c 


Example getting driver specifics. 


Run from CLI only 
/ 


% OF 0 0 Ob OF OE Oe OF 


#include <exec/types.h> 
#include <exec/ports.h> 
#include <devices/printer.h> 
#include <devices/prtbase.h> 


#include <clib/exec_protos.h> 
#include <clib/alib_ protos.h> 
#include <clib/alib stdio_protos.h> 


Compiled with SAS C 5.10a. le -cfist -v -L Printer Data 


Printer Device 181 


union printerIO 


struct IOStdReq ios; 

struct IODRPReq iodrp; 

struct IO0PrtCmdReq iopc; 
)e 


VOID main(VOID); 
VOID main(VOID) 


struct MsgPort *PrinterMP; 
union printerIO *PIO; 

struct PrinterData *PD; 

struct PrinterExtendedData *PED; 


/* Create non-public messageport. Could use CreateMsgPort() for this, that’s 
* V37 specific however. 
x 


if (PrinterMP = (struct MsgPort *)CreatePort (0,0)) 


/* Allocate printerIO union */ 
if (PIO = (union printerIO *)CreateExtIO(PrinterMP, sizeof(union printerI0))) 


/* Open the printer.device */ 
if (! (OpenDevice("printer.device",0, (struct IORequest *)PIO,0))) 
{ 


/* Now that we’ve got the device opened, let’s see what we’ve got. 
* First, get a pointer to the printer data. 
*/ 

PD = (struct PrinterData *)PIO->iodrp.io Device; 

/* And a pointer to the extended data */ 

PED = (struct PrinterExtendedData *) &PD->pd_SegmentData->ps_PED; 


/* See the <devices/prtbase.h> include file for more details on 
* the PrinterData and PrinterExtendedData structures. 
*/ 
printf ("Printername: ’%s’, Version: %tld, Revision: %ld\n", 
PED->ped_PrinterName, PD->pd_SegmentData->ps_Version, 
PD->pd_SegmentData-~>ps Revision); 


printf("PrinterClass: 0x%lx, ColorClass: 0x%lx\n", 
PED->ped PrinterClass, PED->ped_ColorClass); 


printf ("MaxColumns: %ld, NumCharSets: %ld, NumRows: %ld\n", 
PED->ped_MaxColumns, PED->ped_NumCharSets, PED->ped_NumRows) ; 


printf ("MaxXDots: %ld, MaxYDots: %ld, XDotsInch: %ld, YDotsInch: %ld\n", 
PED->ped_MaxXDots, PED->ped_MaxYDots, PED->ped_XDotsInch, PED->ped_YDotsInch) 


CloseDevice((struct IORequest *)PIO); 

} 
else 

printf ("Can’t open printer.device\n") ; 
DeleteExtIO((struct IORequest *) PIO); 
} 


else 

printf ("Can’t CreateExtIO\n"); 
DeletePort ((struct MsgPort *)PrinterMP) ; 
} 


else 
printf("Can’t CreatePort\n"); 
} 


Reading and Changing the Printer Preferences Settings 


The user preferences can be read and changed without running the Workbench Preferences tool. 
Reading printer preferences can be done by referring to PD->pd_Preferences. Listed on the next 
page are the printer Preferences fields and their valid ranges. 


182 Amiga ROM Kernel Reference Manual: Devices 


Text Preferences 


PrintPitch -— PICA, ELITE, FINE 
PrintQuality - DRAFT, LETTER 
PrintSpacing -—  SIX_LPI, EIGHT_LPI 
PrintLeftMargin - 1 to PrintRightMargin 
PrintRightMargin -  PrintLeftMargin to 999 
PaperLength - 1 to 999 
PaperSize -—  US_LETTER, US_LEGAL, N_TRACTOR, W_TRACTOR, 
CUSTOM 
PaperType - FANFOLD, SINGLE 
Graphic Preferences 
PrintImage - IMAGE_POSITIVE, IMAGE_NEGATIVE 
PrintAspect -  ASPECT_HORIZ, ASPECT_VERT 
PrintShade - SHADE_BW, SHADE_GREYSCALE, SHADE_COLOR 
PrintThreshold - 1 to 15 
PrintFlags - CORRECT_RED, CORRECT_GREEN, 


CORRECT_BLUE, CENTER_IMAGE, 
IGNORE_DIMENSIONS, BOUNDED_DIMENSIONS, 
ABSOLUTE_DIMENSIONS, PIXEL_DIMENSIONS, 
MULTIPLY_DIMENSIONS, INTEGER_SCALING, 
ORDERED_DITHERING, HALFTONE_DITHERING, 
FLOYD_DITHERING, ANTL_ALIAS, 


GREY_SCALE2 
PrintMaxWidth - 0 to 65535 
PrintMaxHeight - 0 to 65535 
PrintDensity - 1to7 
PrintX Offset - 0 to 255 


This example program changes various settings in the printer device’s copy of preferences. 


/ 


Set _Prefs.c 

This example changes the printer device’s COPY of preferences (as obtained 
when the printer device was opened by a task via OpenDevice()). Note that 

it only changes the printer device’s copy of preferences, not the preferences 
as set by the user via the preference editor(s). 

Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 


Run from CLI only 


+ 0 OO OO 


™~s 


#include <exec/types.h> 

#include <devices/printer.h> 
#include <devices/prtbase.h> 
#include <intuition/intuition.h> 
#include <intuition/screens.h> 
#include <intuition/preferences.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/alib stdio_ protos.h> 
#include <clib/graphics protos.h> 
#include <clib/intuition_protos.h> 


Printer Device 183 


struct Library *IntuitionBase; 
struct Library *GfxBase; 


union printerIO 

{ 
struct IOStdReq ios; 
struct IODRPReq lodrp; 
struct IOPrtCmdReq iopc; 

Me 


struct MsgPort *PrintMP; 
union printerIO *pio; 


char message[] = "\ 

This is a test message to see how this looks when printed\n\ 
using various printer settings.\n\n"; 

VOID main (VOID); 

VOID DoPrinter (VOID) ; 

int DoTest (VOID); 


VOID main (VOID) 
{ 


if (IntuitionBase = OpenLibrary ("intuition.library", OL) ) 
{ 
if (GfxBase = OpenLibrary ("graphics.library", OL) ) 
DoPrinter(); 


CloseLibrary (GfxBase) ; 
} 


CloseLibrary (IntuitionBase) ; 
} 
} 


VOID DoPrinter (VOID) 
{ 


if (PrintMP = CreatePort (OL, OL) ) 
if (pio = (union printerIO *)CreateExtIO(PrintMP, sizeof (union printerlI0O))) 
{ 
if (! (OpenDevice("printer.device",OL, (struct IORequest *)pio,0OL))) 


{ 
DoTest (); 
CloseDevice((struct IORequest *) pio); 


} 
DeleteExtIO((struct IORequest *) pio); 
} 


DeletePort (PrintMP) ; 
} 
} 


DoTest (VOID) 
{ 


struct PrinterData *PD; 
struct Preferences *prefs; 
UWORD newpitch; 

UWORD newspacing; 


/* Send INIT sequence - make sure printer is inited - some */ 
/* printers may eject the current page if necessary when inited */ 


pio->ios.io_ Command = CMD_WRITE; 
pio->ios.io Data = "\033#1"; 
pio->ios.io Length = -1L; 


if (DoIO((struct IORequest *)pio)) 
return (FALSE); 


/* Print some text using the default settings from Preferences */ 
pio->ios.io_ Command = CMD WRITE; 


pio->ios.io Data = message; 
pio->ios.io Length = -1L; 


184 Amiga ROM Kernel Reference Manual: Devices 


if (DoIO((struct IORequest *) pio) ) 
return (FALSE) ; 


/* Now try changing some settings 

* Note that we could just as well send the printer.device escape 

* sequences to change these settings, but this is an example program. 
*/ 


/* Get pointer to printer data */ 
PD = (struct PrinterData *) pio->ios.io Device; 


/* Get pointer to printer’s copy of preferences 

* Note that the printer.device makes a copy of preferences when 
* the printer.device is successfully opened via OpenDevice(), 

* so we are only going to change the COPY of preferences 


*/ 


prefs = &PD->pd_Preferences; 


/* Change a couple of settings */ 


if (prefs->PrintSpacing == SIX_LPI) 
newspacing = EIGHT LPI; 

if (prefs->PrintSpacing == EIGHT_LPI) 
newspacing = SIX_LPI; 


if (prefs->PrintPitch == PICA) 
newpitch = ELITE; 

if (prefs->PrintPitch == ELITE) 
newpitch = FINE; 

if (prefs->PrintPitch == FINE) 
newpitch = PICA; 


/* And let’s change the margins too for this example */ 


prefs->PrintLeftMargin = 20; 
prefs->PrintRightMargin = 40; 


prefs->PrintPitch = newpitch; 
prefs->PrintSpacing = newspacing; 


/* Send INIT sequence so that these settings are used */ 
pio->ios.io Command = CMD WRITE; 

pio->ios.io Data = "\033#1"; 

pio->ios.io Length = -1L; 


if (DoIO((struct IORequest *) pio) ) 
return (FALSE) ; 


pio->ios.io Command = CMD_WRITE; 
pio->ios.io Data = message; 
pio->ios.io_Length = -1L; 


if (DoIO((struct IORequest *)pio)) 
return (FALSE) ; 


/* Send FormFeed so page is ejected */ 
pio->ios.io Command = CMD WRITE; 
pio->ios.io Data = "\014"; 
pio->ios.io Length = -1L; 


if (DoIO((struct IORequest *) pio) ) 
return (FALSE) ; 


return (TRUE) ; 
} 


Do Your Duty. The application program is responsible for range checking if the user is 
able to change the preferences from within the application. 


Printer Device 185 


Querying the Printer Device 


The status of the printer port and registers can be determined by querying the printer device. The 
information retumed will vary depending on the type of printer—parallel or serial—selected by the 
user. If parallel, the data returned will reflect the current state of the parallel port; if serial, the data 
retumed will reflect the current state of the serial port. 


You query the printer device by passing an IOStdReq to the device with PRD_QUERY set in 
io_Command and a pointer to a structure to hold the status set in io_Data. 
struct PStat 
UBYTE LSB; /* least significant byte of status */ 
UBYTE MSB; /* most significant byte of status */ 
}; 
union printerIO *PrintIO; 
struct PStat status; 
PrintI0O->ios.io Data = &status; /* point to status structure */ 


PrintI0O->ios.io_ Command = PRD_QUERY; 
DoIO((struct IORequest *) request); 


The status is returned in the two UBYTES set in the io_Data field. The printer type, either serial or 
parallel, is retumed in the io_Actual field. 


io_Data Bit Active Function (Serial Device) 
LSB 0 low reserved 
1 low reserved 
2 low reserved 
3 low Data Set Ready 
4 low Clear To Send 
5 low Carrier Detect 
6 low Ready To Send 
7 low Data Terminal Ready 
MSB 8 high read buffer overflow 
9 high break sent (most recent output) 
10 high break received (as latest input) 
11 high transmit x-OFFed 
12 high receive x-OFFed 
13-15 high reserved 
io_Data Bit Active Function (Parallel Device) 
LSB 0 high printer busy (offline) 
1 high paper out 
2 high printer selected 
3 — read=0; write=1 
4-7 reserved 
MSB 8-15 reserved 
io_Actual 1-parallel, 2-serial 


186 Amiga ROM Kernel Reference Manual: Devices 


Error Codes from the Printer Device 


The printer device retums error codes whenever an operation is attempted. There are two types of 
error codes that can be returned. Printer device error codes have positive values; Exec I/O error 
codes have negative values. Therefore, an application should check for a non-zero return code as 
evidence of an error, not simply a value greater than zero. 

PrintIO->ios.io Length = strlen(outbuffer); 

PrintIO->ios.io Data = (APTR) outbuffer; 

PrintIO->ios.io Command = PRD_RAWWRITE; 


if (DoIO((struct IORequest *)PrintIO)) 
printf ("RAW Write failed. Error: %d ",PrintIO->ios.io Error); 


The error is found in io_Error. 


Printer Device Error Codes 


Error Value Explanation 
PDERR_NOERR 0 Operation successful 
PDERR_CANCEL 1 User canceled request 
PDERR_NOTGRAPHICS Z Printer cannot output graphics 
PDERR_INVERTHAM 3 OBSOLETE 
PDERR_BADDIMENSION 4 Print dimensions are illegal 
PDERR_DIMENSIONOVERFLOW = 5 OBSOLETE 
PDERR_INTERNALMEMORY 6 No memory available for internal 
variables 
PDERR_BUFFERMEMORY 7 No memory available for print buffer 


Exec Error Codes 


Error Value Explanation 

IOERR_OPENFAIL -1 Device failed to open 

IOERR_ABORTED -2 Request terminated early (after AbortIO() 
IOERR_NOCMD -3 Command not supported by device 
IOERR_BADLENGTH -4 Not a valid length 


Dumping a Rastport to a Printer 


You dump a RastPort (drawing area) to a graphics capable printer by passing an IODRPRegq to the 
device with PRD-_DUMPRPORT set in io_Command along with several parameters that define 
how the dump is to be rendered. 


union printerIO *PrintIO 
struct RastPort *rastPort; 
struct ColorMap *colorMap; 
ULONG modeid; 

UWORD sx, sy, sw, sh; 

LONG dc, dr; 


UWORD s; 

PrintI0->iodrp.io RastPort = rastPort; /* pointer to RastPort */ 
PrintI0O->iodrp.io ColorMap = colorMap; /* pointer to color map */ 
PrintIO->iodrp.io Modes = modeid; /* ModeID of ViewPort */ 
PrintI0O->iodrp.io SrcX = sx; /* RastPort X offset */ 
PrintI0O->iodrp.io SrcY = sy; /* RastPort Y offset */ 


Printer Device 187 


PrintIO->iodrp.io SrcWidth = sw; /* print width from X offset */ 
PrintIO->iodrp.io SrcHeight = sh; /* print height from Y offset */ 
PrintIO->iodrp.io DestCols = dc; /* pixel width */ 
PrintI0O->iodrp.io DestRows = dr; /* pixel height */ 
PrintIO->iodrp.io Special = /* flags */ 


Ss; 
PrintI0O->iodrp.io Command = PRD _DUMPRPORT; 
SendIO((struct IORequest *) request); 


The asynchronous SendIO() routine is used in this example instead of the synchronous DoIO() 
. A call to DoIOQ does not retum until the I/O request is finished. A call to SendIO() retums 
immediately. This allows your task to do other processing such as checking if the user wants to abort 
the I/O request. It should also be used when writing a lot of text or raw data with CMD_WRITE 
and PRD_RAWWRITE. 


Here is an overview of the possible arguments for the RastPort dump. 


io_RastPort A pointer to a RastPort. The RastPort’s bitmap could be in Fast memory. 
io_ColorMap A pointer to a ColorMap. This could be a custom one. 


io_Modes The viewmode flags or the ModeID retumed from Get VPModeID() (V36). 
io_SrcX X offset in the RastPort to start printing from. 
io_SrcY Y offset in the RastPort to start printing from. 


io_SrcWidth Width of the RastPort to print from io_SreX. 
io_SrcHeight Height of the RastPort to print from io_SrcY. 
io_DestCols Width of the dump in printer pixels. 
io_DestRows Height of the dump in printer pixels. 
io_Special Flag bits (described below). 


Looking at these arguments you can see the enormous flexibility the printer device offers for 
dumping a RastPort. The RastPort pointed to could be totally custom defined. This flexibility 
means it is possible to build a BitMap with the resolution of the printer. This would result in having 
one pixel of the BitMap correspond to one pixel of the printer. In other words, only the resolution 
of the output device would limit the final result. With 12 bit planes and a custom ColorMap, you 
could dump 4096 colors—without the HAM limitation—to a suitable printer. The offset, width 
and height parameters allow dumps of any desired part of the picture. Finally the ViewPort mode, 
io_DestCols, io_DestRows parameters, together with the io_Special flags define how the dump 
will appear on paper and aid in getting the correct aspect ratio. 


PRINTER SPECIAL FLAGS 


The printer special flags (io_Flags) of the IODRPReq provide a high degree of control over the 
printing of a RastPort. 


SPECIAL_ASPECT Allows one of the dimensions to be reduced/expanded to 
preserve the correct aspect ratio of the printout. 

SPECIAL_CENTER Centers the image between the left and right edge of the 
paper. 


SPECIAL_NOFORMFEED Prevents the page from being ejected after a graphics dump. 
Usually used to mix graphics and text or multiple graphics 
dump on a page oriented printer (normally a laser printer). 


188 Amiga ROM Kernel Reference Manual: Devices 


SPECIAL_NOPRINT The print size will be computed, and set inio_DestCols and 
io_DestRows, but won’t print. This way the application 
can see what the actual printsize in printerpixels would be. 


SPECIAL_TRUSTME Instructs the printer not to send a reset before and after the 
dump. This flag is obsolete for V1.3 (and higher) drivers. 
SPECIAL_DENSITY 1-7 This flag bit is set by the user in Preferences. Refer to 


“Reading and Changing the Printer Preferences Settings” 
if you want to change to density of the printout. (Or any 
other setting for that matter.) 


SPECIAL_FULLCOLS The width is set to the maximum possible, as determined 
by the printer or the configuration limits. 

SPECIAL_FULLROWS The height is set to the maximum possible, as determined 
by the printer or the configuration limits. 

SPECIAL_FRACCOLS Informs the printer device that the value in io_DestCols is 


to be taken as a longword binary fraction of the maximum 
for the dimension. For example, if io_DestCols is 0x8000, 
the width would be 1/2 (0x8000 / Oxffff) of the width of the 


paper. 

SPECIAL_FRACROWS Informs the printer device that the value in io_DestRows is 
to be taken as a longword binary fraction for the dimension. 

SPECIAL_MILCOLS Informs the printer device that the value in io_DestCols 


is specified in thousandths of an inch. For example, if 
io_DestCols is 8000, the width of the printout would be 
8.000 inches. 


SPECIAL_MILROWS Informs the printer device that the value in io_DestRows 
is specified in thousandths of an inch. 


The flags are defined in the include file devices/printer.h. 


PRINTING WITH CORRECTED ASPECT RATIO 


Using the special flags it is fairly easy to ensure a graphic dump will have the correct aspect ratio 
on paper. There are some considerations though when printing a non-displayed RastPort. One 
way to get a corrected aspect ratio dump is to calculate the printer’s ratio from XDotsInch and 
YDotsInch (taking into account that the printer may not have square pixels) and then adjust the 
width and height parameters accordingly. You then ask for a non-aspect-ratio-corrected dump since 
you already corrected it yourself. 


Another possibility is having the printer device do it for you. To get a correct calculation you could 
build your RastPort dimensions in two ways: 


1. Using an integer multiple of one of the standard (NTSC) display resolutions and setting the 
io_Modes argument accordingly. For example if your RastPort dimensions were 1280 x 
800 (an even multiple of 640 x 400) you would set io_Modes to LACE | HIRES. Setting the 
SPECIAL_ASPECT flag would enable the printer device to properly calculate the aspect ratio 
of the image. 


Printer Device 189 


2. When using an arbitrary sized RastPort, you can supply the ModeID of a display mode which 
has the aspect ratio you would like for your RastPort. The aspect ratio of the various display 
modes are defined as ticks-per-pixel in the Resolution field of the DisplayInfo structure. You 
can obtain this value from the graphics database. For example, the resolution of Productivity 
Mode is 22:22, in other words, 1:1, perfect for a RastPort sized to the limits of the output 
device. See the “Graphics Library” chapter of the Amiga ROM Kernel Reference Manual: 
Libraries for general information on the graphics system. 


The following example will dump a RastPort to the printer and wait for either the printer to finish 
or the user to cancel the dump and act accordingly. 


/* Demo_Dump.c 

* 

* Simple example of dumping a rastport to the printer, changing 
* printer preferences programmatically and handling error codes. 
* 

* Compile with SAS C 5.10a. le -cfist -v -L Demo_Dump 

* 

* Requires Kickstart V37 

* Run from CLI only 

e/ 


#include <exec/types.h> 

#include <exec/memory.h> 

#include <exec/ports.h> 

#include <devices/printer.h> 
#include <devices/prtbase.h> 
#include <dos/dos.h> 

#include <intuition/intuition.h> 
#include <intuition/screens.h> 
#include <graphics/displayinfo.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/alib stdio_protos.h> 
#include <clib/graphics protos.h> 
#include <clib/intuition_protos.h> 


struct IntuitionBase *IntuitionBase; 
struct GfxBase *GfxBase; 


union printerIO 

{ 
struct IOStdReq los; 
struct IODRPReq ilodrp; 
struct IOPrtCmdReq iopc; 

ie 


struct EasyStruct reqES = 

{ 
sizeof (struct EasyStruct), 0, "DemoDump", 
"Ss", 
NULL, 

}; 


/* Possible printer.device and I/O errors */ 
static UBYTE *ErrorText[] = 
{ 


"PDERR_NOERR", 
"PDERR_CANCEL", 
"PDERR_NOTGRAPHICS", 
“INVERTHAM", /* OBSOLETE */ 
“BADDIMENSION", 
“"DIMENSIONOVFLOW", /* OBSOLETE */ 
"INTERNALMEMORY", 
"BUFFERMEMORY", 
/* IO_ERRs */ 
“IOERR_OPENFAIL", 
"IOERR_ABORTED", 
“IOERR_NOCMD", 
"IOERR_BADLENGTH" 
he 


190 Amiga ROM Kernel Reference Manual: Devices 


/* Requester Action text */ 
static UBYTE *ActionText[] = 


"OK|CANCEL", 
"Continue", 
"Abort", 

Me 


#define OKCANCELTEXT 0 
#define CONTINUETEXT 1 
#define ABORTTEXT 2 


VOID main(VOID) ; 
VOID main (VOID) 
{ 


struct MsgPort *PrinterMP; 
union printerIO *PIO; 

struct PrinterData *PD; 

struct PrinterExtendedData *PED; 
struct Screen *pubscreen; 

struct ViewPort *vp; 

STRPTR textbuffer; 

LONG modeID, i,j; 

ULONG dcol[5], drow[5]; 

ULONG signal; 


/* Fails silently if not V37 or greater. Nice thing to do would be to put up 
* a V33 requester of course. 


a 


/* Set up once */ 
reqES.es GadgetFormat = ActionText [CONTINUETEXT] ; 


if (IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", 37)) 


{ 

/* Using graphics.library to get the displaymodeID of the public screen, 
* which we’ll pass to the printer.device. 

x/ 

if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37)) 


{ 
if (textbuffer = (STRPTR)AllocMem(256, MEMF CLEAR) ) 
{ 


/* Create non-public messageport. Since we depend on V37 already, we’1ll 
* use the new Exec function. 
* 


if (PrinterMP = CreateMsgPort () ) 


/* Allocate printerIO union */ 
if (PIO = (union printerIO *)CreateExtIO(PrinterMP, sizeof(union printerI0))) 


/* Open the printer.device */ 
if (! (OpenDevice ("printer.device",0, (struct IORequest *)PIO,0))) 
{ 


/* Yahoo, we’ve got it. 

* We’ll use the PrinterData structure to get to the the printer 
* preferences later on. The PrinterExtendedData structure will 
* reflect the changes we’ll make to the preferences. 


*/ 


PD = (struct PrinterData *)PIO->iodrp.io Device; 

PED = (struct PrinterExtendedData *) &PD->pd_SegmentData->ps_ PED; 
/* We're all set. We’1ll grab the default public screen (normally 
* Workbench) and see what happens when we dump it with different 
* densities. 

* Next we’ll put up a nice requester for the user and ask if 

* (s)he wants to actually do the dump. 

*/ 


if (pubscreen = LockPubScreen (NULL) ) 
vp = &(pubscreen->ViewPort); 


/* Use graphics.library/GetVPModeID() to get the ModeID of the screen. */ 
if ((modeID = GetVPModeID(vp)) != INVALID_ID) 
{ 


Printer Device 191 


/* Seems we got a valid ModeID for the default public screen (surprise). 
* Do some fake screen dumps with densities 1, 3, 5 and 7. Depending on 


* the driver, one or more may be the same. 
*/ 


/* Pill in those parts of the IODRPRequest which won’t change */ 
PIO->iodrp.io Command = PRD_DUMPRPORT; 

PIO->iodrp.io RastPort = &(pubscreen->RastPort) ; 

PIO->iodrp.io ColorMap = vp->ColorMap; 

PIO->iodrp.io Modes = modeID; 

PIO->iodrp.io SrcX = pubscreen->LeftEdge; 

PIO->iodrp.io SrcY = pubscreen->TopEdge; 

PIO->iodrp.io SrcWidth = pubscreen->Width; 

PIO->iodrp.io SrcHeight = pubscreen->Height; 


for (i = 1,j=0; i < 8; it=2, j++) 
{ 


/* On return these will contain the actual dump dimension */ 
PIO->iodrp.io DestCols = 0; 
PI0->iodrp.io DestRows = 0; 
/* We'll simply change our local copy of the 
* Preferences structure. Likewise we could change 
* all printer-related preferences. 
*/ 
PD->pd_Preferences.PrintDensity = i; 
PI0->iodrp.io Special = SPECIAL_NOPRINT|SPECIAL_ASPECT; 


/* No need to do asynchronous I/O here */ 
DoIO((struct IORequest *) PIO); 


if (PIO->iodrp.io Error == 0) 


{ 
dcol[j] = PI0->iodrp.io DestCols; 
drow[{j] = PI0->iodrp.io DestRows; 
} 
else 
{ 
j = PIO->iodrp.io Error; 
if (j < 0) 
gjej*-14+7; 


sprintf (textbuffer, "Error: %s\n", ErrorText[j]); 
reqES.es GadgetFormat = ActionText [CONTINUETEXT]; 
EasyRequest (NULL, &reqES, NULL, textbuffer) ; 
break; 


} 


/* Simple, lazy way to check if we encountered any problems */ 
if (i == 9) 


/* Build an ‘intelligent’ requester */ 
sprintf (textbuffer, 
"$s: &$5ld x $5ld\n%s: %$5ld x &$5ld\n%s: &51d x%5ld\n%s: %51d x &5ld\n\n%s", 
"Density 1", dcol[0], drow[0], 
"Density 3", dcol(1], drow[1], 
"Density 5", dcol[(2], drow[2], 
"Density 7", dcol[(3], drow[3], 
"Print screen at highest density?"); 
reqES.es_ GadgetFormat = ActionText [OKCANCELTEXT] ; 


~ 


Ph + + HH OH HE 
~ 


Obviously the choice presented to the user here is a very 
simple one. To print or not to print. In a real life 
application, a requester could be presented, inviting 
the user to select density, aspect, dithering etc. 
The fun part is, of course, that the user can, to a certain 
degree, be informed about the effects of her/his selections. 
if (EasyRequest (NULL, &reqES, NULL, textbuffer) ) 
/* We've still got the density preference set to the highest 
* density, so no need to change that. 
* All we do here is re-initialize io DestCols/Rows and remove 
* the SPECIAL NOPRINT flag from io Special. 
*/ 
PIO->iodrp.io_DestCols 0; 
P1I0->iodrp.io DestRows = 0; 
PIO->iodrp.io Special &= ~SPECIAL_NOPRINT; 


192 Amiga ROM Kernel Reference Manual: Devices 


* Always give the user a change to abort. 

* So we'll use SendIO(), instead of DoIO(), to be asynch and 

* catch a possible user request to abort printing. Normally, 

* the user would be presented with a nice, fat, ABORT requester. 
* However, since this example doesn’t even open a window, and is 
* basically a '’GraphicDumpDefaultPubscreen’ equivalent, we’ll use 
* CTRL-C as the user-abort. Besides that, got to keep it short. 

* 


SendIO((struct IORequest *) PIO); 


/* Now Wait() for either a user signal (CTRL-C) or a signal from 
* the printer.device 
* 


signal = Wait(1 << PrinterMP->mp_SigBit | SIGBREAKF_CTRL_C); 
if (signal & SIGBREAKF_CTRL C) 
{ 


/* User wants to abort */ 
AbortIO((struct IORequest *) PIO); 
WaitIO((struct IORequest *)PIO); 
} 


if (signal & (1 << PrinterMP->mp_SigBit)) 
{ 


/* printer is either ready or an error has occurred */ 
/* Remove any messages */ 

while (GetMsg (PrinterMP) ); 

} 


/* Check for errors (in this case we count user-abort as an error) */ 
if (PIO->iodrp.io Error != 0) 


{ 
j = PI0->iodrp.io Error; 
if (j < 0) 
fe Gel 
sprintf (textbuffer, "Error: %s\n", ErrorText[j]); 
reqES.es GadgetFormat = ActionText [CONTINUETEXT] ; 
EasyRequest (NULL, &reqES, NULL, textbuffer); 
} 


} /* else user doesn’t want to print */ 
} 
} 


else 

/* Say what? */ 

EasyRequest (NULL, &reqES, NULL, "Invalid ModeID\n") ; 
UnlockPubScreen (NULL, pubscreen) ; 
} 


else 
EasyRequest (NULL, &reqES, NULL, "Can’t lock Public Screen\n"); 


CloseDevice((struct IORequest *)PIO); 
} 
else 
EasyRequest (NULL, &reqES, NULL, "Can’t open printer.device\n") ; 


DeleteExtIO((struct IORequest *) PIO); 

} 
else 

EasyRequest (NULL, &reqES, NULL, "Can’t create Extented I/O Request\n"); 
DeleteMsgPort (PrinterMP) ; 
} 


else 

EasyRequest (NULL, &reqES, NULL, "Can’t create Message port\n"); 
/* else Out of memory? 256 BYTES? */ 
FreeMem(textbuffer, 256) ; 


} 
CloseLibrary (GfxBase) ; 


} /* else MAJOR confusion */ 
CloseLibrary (IntuitionBase) ; 


Printer Device 193 


STRIP PRINTING 


Strip printing is a method which allows you to print a picture that normally requires a large print 
buffer when there is not much memory available. This would allow, for example, a RastPort to be 
printed at a higher resolution than it was drawn in. Strip printing is done by creating a temporary 
RastPort as wide as the source RastPort, but not as high. The source RastPort is then rendered, 
a strip at a time, into the temporary RastPort which is dumped to the printer. 


The height of the strip to dump must be an integer multiple of the printer’s NumRows if a non- 
aspect-ratio-corrected image is to be printed. 


For an aspect-ratio-corrected image, the SPECIAL_NOPRINT flag will have to be used to find an 
io_DestRows that is an integer multiple of NumRows. This can be done by varying the source 
height and asking for a SPECIAL_NOPRINT dump until io_DestRows holds a number that is an 
integer multiple of the printer’s NumRows. 


If smoothing is to work with strip printing, a raster line above and below the actual area should be 
added. The line above should be the last line from the previous strip, the line below should be the 
first line of the next strip. Of course, the first strip should not have a line added above and the last 
strip should not have a line added below. 


The following is a strip printing procedure for a RastPort which is 200 lines high. 


First strip 
copy source line 0 through 50 (51 lines) to strip RastPort lines 0 through 50 (51 lines). 
io_SrcY = 0, io_Height = 50. 
° the printer device can see there is no line above the first line to dump (since SrcY = 0) 
and that there is a line below the last line to dump (since there is a 51 line RastPort and 
only 50 lines are dumped). 


Second strip 
° copy source line 49 through 100 (52 lines) to strip RastPort lines 0 
through 51 (S52 lines). 
e io_SrcY = 1, io_Height = 50. 
° the printer device can see there is a line above the first line to dump (since SrcY = 1) 
and that there is a line below the last line to dump (since there is a 52 line RastPort and 
only 50 lines are dumped). 


Third strip 
° copy source line 99 through 150 (52 lines) to strip RastPort lines 0 through 51 (52 lines). 
e io_SrcY = 1, io_Height = 50. 
° the printer device can see there is a line above the first line to dump (since SrcY = 1) 
and that there is a line below the last line to dump (since there is a 52 line RastPort and 
only 50 lines are dumped). 


Fourth strip 
° copy source line 149 through 199 (51 lines) to strip RastPort lines 0 through SO (51 lines). 
e io_SrcY = 1, io_Height = 50. 
° the printer device can see there is a line above the first line to dump (since SrcY = 1) 
and that there is no line below the last line to dump (since there is a 51 line RastPort 
and only 50 lines are dumped). 


194 Amiga ROM Kernel Reference Manual: Devices 


ADDITIONAL NOTES ABOUT GRAPHIC DUMPS 


1. 


nn & W N 


When dumping a 1 bitplane image select the black and white mode in Preferences. This is 
much faster than a grey-scale or color dump. 


. Horizontal dumps are much faster than vertical dumps. 

. Smoothing doubles the print time. Use it for final copy only. 

. F-S dithering doubles the print time. Ordered and half-tone dithering incur no extra overhead. 
. The lower the density, the faster the printout. 


. Friction-fed paper tends to be much more accurate than tractor-fed paper in terms of vertical 


dot placement (i.e., less horizontal strips or white lines). 


. Densities which use more than one pass tend to produce muddy grey-scale or color printouts. 


It is recommended not to choose these densities when doing a grey-scale or color dump. 


Keep This in Mind. It is possible that the printer has been instructed to receive a certain 
amount of data and is still in an “expecting” state if an I/O request has been aborted by the 
user. This means the printer would try to finish the job with the data the next I/O request 
might send. Currently the best way to overcome this problem is for the printer to be reset. 


Printer Device 195 


Creating a Printer Driver 


Creating the printer-dependent modules for the printer device involves writing the data structures 
and code, compiling and assembling them, and linking to produce an Amiga binary object file. 
The modules a driver contains varies depending on whether the printer is non-graphics or graphics 
capable. 


All drivers contain these modules: 


macros.i - include file for init.asm, contains printer device macro definitions 

printertag.asm - printer specific capabilities such as density, character sets and color 

init.asm - opens the various libraries required by the printer driver. This will 
be the same for all printers 

data.c - contains printer device RAW commands and the extended charac- 
ter set supported by the printer 

dospecial.c - printer specific special processing required for printer device com- 
mands like aSLRM and aSFC 

Graphic printer drivers require these additional modules: 

render.c - printer specific processing to do graphics output and fill the output 
buffer 

transfer.c - printer specific processing called by render.c to output the buffer 
to the printer. Code it in assembly if speed is important 

density.c - printer specific processing to construct the proper print density 
commands 


The first piece of the printer driver is the PrinterSegment structure described in devices/prtbase.h 
(this is pointed to by the BPTR retumed by the LoadSeg() of the object file). The PrinterSegment 
contains the PrinterExtendedData (PED) structures (also described in devices/prtbase.h) at the 
beginning of the object. The PED structure contains data describing the capabilities of the printer, 
as well as pointers to code and other data. Here is the assembly code for a sample PrinterSegment, 
which would be linked to the beginning of the sequence of files as printertag.asm. 


ROO IOI III III IIIT IO III IOI Ik 


x 

7 printer device dependent code tag 

* 

* 

* 

Ok koko koko oko ok kkk oko kok kaikki kkk ok 
SECTION printer 

Keceeon Included Files ~----------------- 99 - nn nn nna 
INCLUDE "exec/types.i" 
INCLUDE "exec/nodes.i" 
INCLUDE "exec/strings.i" 
INCLUDE “epsonX_rev.i" ; contains VERSION & REVISION 
INCLUDE "devices/prtbase.i" 

Fan menn Imported Names -------- 99 rn rr nnn nnn 
XREF _Init 
XREF _Expunge 
XREF _Open 
XREF _Close 


196 Amiga ROM Kernel Reference Manual: Devices 


XREF _CommandTable 
XREF _PrinterSegmentData 
XREF _DoSpecial 
XREF _Render 
XREF _ExtendedCharTable 
keen Exported NameS --------- 2929-2 nn ree nnn 
XDEF _PEDData 


KK I IK IK IK I IK KKK KK KR KKK IK KR KKK KKK KKK KEK KKK KE KKK KKK KKK KEK KKK KKK KKK 


; in case anyone tries to execute this 
MOVEQ #0,D0 


RTS 
DC.W VERSION > must be at least 35 (V1.3 and up) 
DC.W REVISION ; your own revision number 
_PEDData: 
Dc.L printerName ; pointer to the printer name 
Dc.L _Init ; pointer to the initialization code 
Dc.L _Expunge ; pointer to the expunge code 
bc.L _Open ; pointer to the open code 
Dc.L _Close ; pointer to the close code 
Dc.B PPC_COLORGFX 3; PrinterClass 
DC.B PCC_YMCB 3 ColorClass 
DC.B 136 3 MaxColumns 
DC.B 10 3 NumCharSets 
DC.W 8 ; NumRows 
DC.L 1632 3; MaxXDots 
Dc.L 0 ; MaxYDots 
DC.W 120 7 XDotsInch 
DC.W 712 ; YDotsInch 
pc.L _CommandTable ; pointer to Command strings 
Dc.L _DoSpecial ; pointer to Command Code function 
Dc.L _Render ; pointer to Graphics Render function 
Dc.L 30 ; Timeout 
DC.L _ExtendedCharTable ; pointer to 8BitChar table 
DS.L 1 ; Flag for PrintMode (reserve space) 
Dc.L 0) 7 pointer to ConvFune (char conversion function) 
printerName: 
DC.B ‘Epsonx’ 
DC.B 0 
END 


The printer name should be the brand name of the printer that is available for use by programs 
wishing to be specific about the printer name in any diagnostic or instruction messages. The four 
functions at the top of the structure are used to initialize this printer-dependent code: 


(*(PED->ped_Init))(PD) ; 
This is called when the printer-dependent code is loaded and provides a pointer to the printer 


device for use by the printer-dependent code. It can also be used to open up any libraries or 
devices needed by the printer-dependent code. 


(*(PED->ped_Expunge))() ; 
This is called immediately before the printer-dependent code is unloaded, to allow it to close 
any resources obtained at initialization time. 
(*(PED->ped_Open))(ior) ; 
This is called in the process of an OpenDevice() call, after the Preferences are read and the 
correct primitive I/O device (parallel or serial) is opened. It must return zero if the open is 
successful, or non-zero to terminate the open and retum an error to the user. 
(*(PED->ped_Close))(ior) ; 
This is called in the process of a CloseDevice() call to allow the printer-dependent code to 
close any resources obtained at open time. 


Printer Device 197 


The pd_ variable provided as a parameter to the initialization call is a pointer to the PrinterData 
structure described in devices/prtbase.h. This is also the same as the io_Device entry in printer I/O 
requests. 


pd_SegmentData 
This points back to the PrinterSegment, which contains the PED. 


pd_PrintBuf 
This is available for use by the printer-dependent code—it is not otherwise used by the printer 
device. 


(*pd_PWrite)(data, length); 
This is the interface routine to the primitive I/O device. This routine uses two I/O requests to 
the primitive device, so writes are double-buffered. The data parameter points to the byte data 
to send, and the length is the number of bytes. 


(*pd_PBothReady)(); 
This waits for both primitive I/O requests to complete. This is useful if your code does not want 
to use double buffering. If you want to use the same data buffer for successive pd_PWrites, 
you must separate them with a call to this routine. 


pd_Preferences 
This is the copy of Preferences in use by the printer device, obtained when the printer was 
opened. 


The timeout field is the number of seconds that an I/O request from the printer device to the 
primitive I/O device (parallel or serial) will remain posted and unsatisfied before the timeout 
requester is presented to the user. The timeout value should be long enough to avoid the requester 
during normal printing. 


The PrintMode field is a flag which indicates whether text has been printed or not (1 means printed, 
O means not printed). This flag is used in drivers for page oriented printers to indicate that there is 
no alphanumeric data waiting for a formfeed. 


WRITING AN ALPHANUMERIC PRINTER DRIVER 


The alphanumeric portion of the printer driver is designed to convert ANSI x3.64 style commands 
into the specific escape codes required by each individual printer. For example, the ANSI code for 
underline-on is ESC[4m. The Commodore MPS-1250 printer would like a ESC[-1 to set underline- 
on. The HP LaserJet accepts ESC[&dD as a start underline command. By using the printer driver, 
all printers may be handled in a similar manner. 


There are two parts to the alphanumeric portion of the printer driver: the CommandTable data 
table and the DoSpecial() routine. 


198 Amiga ROM Kernel Reference Manual: Devices 


Command Table 


The CommandTable is used to convert all escape codes that can be handled by simple substitution. 
It has one entry per ANSI command supported by the printer driver. When you are creating a 
custom CommandTable, you must maintain the order of the commands in the same sequence as 
that shown in devices/printer.h. By placing the specific codes for your printer in the proper positions, 
the conversion takes place automatically. 


Octal knows NULL. If the code for your printer requires a decimal 0 (an ASCII NULL 
character), you enter this NULL into the CommandTable as octal 376 (decimal 254). 


Placing an octal value of 377 (255 decimal) in a position in the command table indicates to the printer 
device that no simple conversion is available on this printer for this ANSI command. For example, 
if a daisy-wheel printer does not have a foreign character set, 377 octal (255 decimal) is placed 
in that position in the command table. However, 377 in a position can also mean that the ANSI 
command is to be handled by code located in the DoSpecial() function. For future compatibility all 
printer commands should be present in the command table, and those not supported by the printer 
filled with the dummy entry 377 octal. 


DoSpecial() 


The DoSpecial() function is meant to implement all the ANSI functions that cannot be done by 
simple substitution, but can be handled by a more complex sequence of control characters sent to 
the printer. These are functions that need parameter conversion, read values from Preferences, and 
so on. Complete routines can also be placed in dospecial.c. For instance, in a driver for a page 
oriented-printer such as the HP LaserJet, the dummy Close() routine from the init.asm file would 
be replaced by a real Close() routine in dospecial.c. This close routine would handle ejecting the 
paper after text has been sent to the printer and the printer has been closed. 


The DoSpecial() function is set up as follows: 


#include "exec/types.h" 
#include "devices/printer.h" 
#include "devices/prtbase.h" 


extern struct PrinterData *PD; 


DoSpecial (command, outputBuffer, vline, currentVMI, crlfFlag, Parms) 
UBYTE outputBuffer[]; 

UWORD *command; 

BYTE *vline; 

BYTE *currentVMI; 

BYTE *crlfFlag; 

UBYTE Parms[]; 

{ /* code begins here... */ 


where 


command 
points to the command number. The devices/printer.h file contains the definitions for the 
routines to use (aRIN is initialize, and so on). 


vline 
points to the value for the current line position. 


currentVMI 
points to the value for the current line spacing. 


Printer Device 199 


crifFlag 
points to the setting of the “‘add line feed after carriage return” flag. 


Parms 
contain whatever parameters were given with the ANSI command. 


outputBuffer 
points to the memory buffer into which the converted command is retumed. 


Almost every printer will require an aRIN (initialize) command in DoSpecial(). This command 
reads the printer settings from Preferences and creates the proper control sequence for the specific 
printer. It also returns the character set to normal (not italicized, not bold, and so on). Other 
functions depend on the printer. 


Certain functions are implemented both in the CommandTable and in the DoSpecial() routine. 
These are functions such as superscript, subscript, PLU (partial line up), and PLD (partial line 
down), which can often be handled by a simple conversion. However, some of these functions must 
also adjust the printer device’s line-position variable. 


Save the Data! Some printers lose data when sent their own reset command. For this 
reason, it is recommended that if the printer’s own reset command is going to be used, 
PD->pd_PWaitEnabled should be defined to be a character that the printer will not print. 
This character should be put in the reset string before and after the reset character(s) in the 
command table. 


In the EpsonX[CBM_MPS- 1250] DoSpecial() function you’ll see 


if (*command == aRIS) 
{ /* reset command */ 
PD->pd_PWaitEnabled = \375; /* preserve that data! */ 


while in the command table the string for reset is defined as "\375\033@\375". This means that 
when the printer device outputs the reset string "\033@", it will first see the "\375", wait a second 
and output the reset string. While the printer is resetting, the printer device gets the second "\375" 
and waits another second. This ensures that no data will be lost if a reset command is embedded in 
a string. 


Printertag.asm 


For an alphanumeric printer the printer-specific values that need to be filled in printertag.asm are 
as follows: 


MaxColumns 
the maximum number of columns the printer can print across the page. 


NumCharSets 
the number of character sets which can be selected. 


8BitChars 
a pointer to an extended character table. If the field is null, the default table will be used. 


ConvFunc 
a pointer to a character conversion routine. If the field is null, no conversion routine will be 
used. 


200 Amiga ROM Kernel Reference Manual: Devices 


Extended Character Table 


The 8BitChars field could contain a pointer to a table of characters for the ASCII codes $A0 to 
$FF. The symbols for these codes are shown in the “IFF Appendix” of this manual. If this field 
contains a NULL, it means no specific table is provided for the driver, and the default table is to be 
used instead. 


Care should be taken when generating this table because of the way the table is parsed by the 
printer device. Walid expressions in the table include \011 where 011 is an octal number, \\000 
for null and \\n where n is a 1 to 3 digit decimal number. To enter an actual backslash in the 
table requires the somewhat awkward \\\\. As an example, here is a list of the first entries of the 
EpsonxX[CBM_MPS-1250] table: 


char *ExtendedCharTable[] = 
{ 


eae: /* NBSP */ 
"\033R\007(\033R\\0", /* i */ 
"c\010|", /* cl */ 
"\O33R\003#\033R\\0", /* L- */ 
"\033R\005$\033R\\0", /* 0 */ 
"\O033R\010\\\\\033R\\0", /* Y- */ 

we /* | x/ 
"\033R\002@\033R\\0", /* SS */ 
"\033R\001~\033R\\0", [x wo 

"co", /* copyright */ 
"\033S\\0a\010_\033T", /*a_ * 

we, /* << */ 

a /* 3 */ 

wun, /* SHY x/ 

CEM, /* registered trademark */ 
Wom. /* sail x/ 


/* more entries go here */ 


Ye 


Character Conversion Routine 


The ConvFunc field contains a pointer to a character conversion function that allows you to 
selectively translate any character to a combination of other characters. If no translation conversion 
is necessary (for most printers it isn’t), the field should contain a null. 


ConvFunc() arguments are a pointer to a buffer, the character currently processed, and a CR/LF 
flag. The ConvFunc() function should retum a -1 if no conversion has been done. If the character 
is not to be added to the buffer, a 0 can be returned. If any translation is done, the number of 
characters added to the buffer must be returned. 


Besides simple character translation, the ConvFunc() function can be used to add features like 
underlining to a printer which doesn’t support them automatically. A global flag could be introduced 
that could be set or cleared by the DoSpecial() function. Depending on the status of the flag the 
ConvFunc() routine could, for example, put the character, a backspace and an underline character 
in the buffer and return 3, the number of characters added to the buffer. 


The ConvFunc() function for this could look like the following example: 


#define DO_UNDERLINE 0x01 
#define DO_BOLD 0x02 
/* etc */ 


external short myflags; 
int ConvFunc(buffer, c, crlf_flag) 


char *buffer, c; 
int crlf_flag 


Printer Device 201 


int nr_of_ chars added = 0; 


/* for this example we only do this for chars in the 0x20-0x7e range */ 
/* Conversion of ESC (0xlb) and CSI (0x9b) is NOT recommended */ 


if (c > Oxlf && c < Ox7f) 

{ /* within space - ~ range ? */ 
if (myflags & DO UNDERLINE) 
{ 


*buffert+t+ = c; /* the character itself */ 
*buffer++ = 0x08; /* a backspace */ 

*buffert+ = ' '; /* an underline char */ 

nr_of_ chars added = 3; /* added three chars to buffer */ 


} 
if (myflags & DO BOLD) 
{ 


if (nr_of_chars_ added) 


{ /* already have added something */ 
*buffer++ = 0x08; /* so we start with backspace */ 
++nr_of chars added; /* and increment the counter */ 
*buffer++ = c; 
*buffert++ = 0x08; 


*buffertt+t = c; 
++nr_of chars added; 
if (myflags & DO_UNDERLINE) 


{ /* did we do underline too? */ 

*buffer++ = 0x08; /* then backspace again */ 
*buffert+ = ' '; /* (printer goes crazy by now) */ 
nr_of_chars_ added += 2; /* two more chars */ 


} 
} 


} 
if (nr_of_chars_ added) 

return(nr_of chars added); /* total nr of chars we added */ 
else 

return (-1); /* we didn’t do anything */ 


In DoSpecial() the flagbits could be set or cleared, with code like the following: 


if (*command == aRIS) /* reset command */ 
myflags = 0; /* clear all flags */ 
if (*command == aRIN) /* initialize command */ 


myflags = 0; 


if (*command == aSGRO) /* ‘PLAIN’ command */ 
myflags = 0; 
if (*command == aSGR4) /* underline on */ 
myflags |= DO_UNDERLINE; /* set underline bit */ 
if (*command == aSGR24) /* underline off */ 
myflags &= ~DO_UNDERLINE; /* clear underline bit */ 
if (*command == aSGR1) /* bold on */ 
myflags |= DO BOLD; /* set bold bit */ 
if (*command == aSGR22) /* bold off */ 
myflags &= ~DO BOLD; /* clear bold bit */ 


Try to keep the expansions to a minimum so that the throughput will not be slowed down too much, 
and to reduce the possibility of data overrunning the printer device buffer. 


202 Amiga ROM Kernel Reference Manual: Devices 


WRITING A GRAPHICS PRINTER DRIVER 


Designing the graphics portion of a custom printer driver consists of two steps: writing the printer- 
specific Render(), Transfer() and SetDensity() functions, and replacing the printer-specific values 
in printertag.asm. Render(), Transfer() and SetDensity() comprise render.c, transfer.c, and den- 
sity.c modules, respectively. 


A printer that does not support graphics has a very simple form of Render(Q); it retums an error. 
Here is sample code for Render() for a non-graphics printer (such as an Alphacom or Diablo 630): 


#include "exec/types.h" 
#include "devices/printer.h" 
int Render () 


return (PDERR_NOTGRAPHICS) ; 


The following section describes the contents of a typical driver for a printer that does support 
graphics. 


Render() 


This function is the main printer-specific code module and consists of seven parts referred to here 
as Cases: 
e Pre-Master initialization (Case 5) 
e Master initialization (Case 0) 
Putting the pixels in a buffer (Case 1) 
Dumping a pixel buffer to the printer (Case 2) 


e Closing down (Case 4) 
e Clearing and initializing the pixel buffer (Case 3) 
e Switching to the next color(Case 6) (special case for multi-color printers) 
State Your Case. The numbering of the cases reflects the value of each step as a case in 


a C-language switch statement. It does not denote the order that the functions are executed; 
the order in which they are listed above denotes that. 


For each case, Render() receives four long variables as parameters: ct, x, y and status. These 
parameters are described below for each of the seven cases that Render() must handle. 


Pre-Master initialization (Case 5) 


Parameters: 
ct — 0 or pointer to the IODRPRegq structure passed to PCDumpRPort 
x — io_Special flag from the IODRPRegq structure 
y—0O 


When the printer device is first opened, Render() is called with ct set to 0, to give the driver a 
chance to set up the density values before the actual graphic dump is called. 


The parameter passed in x will be the io_Special flag which contains the density and other SPECIAL 
flags. The only flags used at this point are the DENSITY flags, all others should be ignored. Never 
call PWrite(Q) during this case. When you are finished handling this case, retum PDERR_NOERR. 


Printer Device 203 


Master initialization (Case 0). 


Parameters: 
ct — pointer to a IODRPRegq structure 
x — width (in pixels) of printed picture 
y — height (in pixels) of printed picture 


Everything is A-OK. At this point the printer device has already checked that the values 
are within range for the printer. This is done by checking values listed in printertag.asm. 


The x and y value should be used to allocate enough memory for a command and data buffer for 
the printer. If the allocation fails, PDERR-BUFFERMEMORY should be retumed. In general, the 
buffer needs to be large enough for the commands and data required for one pass of the print head. 
These typically take the following form: 


<start gfx cmd> <data> <end gfx cmd> 


The <start gfx cmd> should contain any special, one-time initializations that the printer might 
require such as: 


e Carriage Retum—some printers start printing graphics without retuming the printhead. Sending 
a CR assures that printing will start from the left edge. 


e Unidirectional—some printers which have a bidirectional mode produce non-matching vertical 
lines during a graphics dump, giving a wavy result. To prevent this, your driver should set the 
printer to unidirectional mode. 


e Clear margins—some printers force graphic dumps to be done within the text margins, thus 
they should be cleared. 


e Other commands—enter the graphics mode, set density, etc. 


Multi-Pass? Don't Forget the Memory. In addition to the memory for commands and 
data, a multi-pass color printer must allocate enough buffer space for each of the different 
color passes. 


The printer should never be reset during the master initialization case This will cause prob- 
lems during multiple dumps. Also, the pointer to the IODRPReq structure in ct should not 
be used except for those rare printers which require it to do the dump themselves. Retum the 
PDERR_TOOKCONTROL error in that case so that the printer device can exit gracefully. 


PDERR_TOOKCONTROL, An Error in Name Only. The printer device error code, 
PDERR_TOOKCONTROL, is not an error at all, but an internal indicator that the printer 
driver is doing the graphic dump entirely on its own. The printer device can assume the 
dump has been done. The calling application will not be informed of this, but will receive 
PDERR_NOERR instead. 


The example render.c functions listed at the end of this chapter use double buffering to reduce the 
dump time which is why the AllocMem() calls are for BUFSIZE times two, where BUFSIZE 
represents the amount of memory for one entire print cycle. However, contrary to the example 
source code, allocating the two buffers independently of each other is recommended. A request for 
one large block of contiguous memory might be refused. Two smaller requests are more likely to 
be granted. 


204 Amiga ROM Kernel Reference Manual: Devices 


Putting the pixels in a buffer (Case 1). 


Parameters: 
ct — pointer to a PrtInfo structure. 
x — PCM color code (if the printer is PCC_MULTLPASS). 
y — printer row # (the range is 0 to pixel height - 1). 


In this case, you are passed an entire row of YMCB intensity values (Yellow, Magenta, Cyan, 
Black). To handle this case, you call the Transfer() function in the transfer.c module. You should 
retum PDERR_NOERR after handling this case. The PCM-defines for the x parameter from the 
file devices/prtgfx.h are PCMYELLOW, PCMMAGENTA, PCMCYAN and PCMBLACK. 


Dumping a pixel buffer to the printer (Case 2). 


Parameters: 
ct—0 
x—0O 
y — # of rows sent (the range is 1 to NumRows). 


At this point the data can be Run Length Encoded (RLE) if your printer supports it. If the printer 
doesn’t support RLE, the data should be white-space stripped. This involves scanning the buffer 
from end to beginning for the position of the first occurrence of a non-zero value. Only the data 
from the beginning of the buffer to this position should be sent to the printer. This will significantly 
reduce print times. 


The value of y can be used to advance the paper the appropriate number of pixel lines if your printer 
supports that feature. This helps prevent white lines from appearing between graphic dumps. 


You can also do post-processing on the buffer at this point. For example, if your printer uses the 
hexadecimal number $03 as a command and requires the sequence $03 $03 to send $03 as data, 
you would probably want to scan the buffer and expand any $03s to $03 $03 during this case. Of 
course, you'll need to allocate space somewhere in order to expand the buffer. 


The error from PWrite() should be returned after this call. 


Clearing and initializing the pixel buffer (Case 3) 


Parameters: 
ct —0 
x—0O 
y—0 


The printer driver does not send blank pixels so you must initialize the buffer to the value your 
printer uses for blank pixels (usually 0). Clearing the buffer should be the same for all printers. 
Initializing the buffer is printer specific, and it includes placing the printer-specific control codes in 
the buffer before and after the data. 


This call is made before each Case 2 call. Clear your active print buffer — remember you are double 
buffering—and initialize it if necessary. After this call, PDERR_-NOERR should be returned. 


Printer Device 205 


Closing Down (Case 4). 
Parameters: ct — error code 
x — io_Special flag from the IODRPRegq structure 
y—O 


This call is made at the end of the graphic dump or if the graphic dump was cancelled for some 
reason. At this point you should free the printer buffer memory. You can determine if memory 
was allocated by checking that the value of PD->pd_PrintBuf is not NULL. If memory was 
allocated, you must wait for the print buffers to clear (by calling PBothReady) and then deallocate 
the memory. If the printer—usually a page oriented printer—requires a page eject command, it can 
be given here. Before you do, though, you should check the SPECIAL_NOFORMFEED bit in x. 
Don’t issue the command if it is set. 


If the error condition in ct is PDERR_CANCEL, you should not PWrite(). This error indicates that 
the user is trying to cancel the dump for whatever reason. Each additional PWrite() will generate 
another printer trouble requester. Obviously, this is not desirable. 

During this render case PWrite(Q) could be used to: 


e reset the line spacing. If the printer doesn’t have an advance ’n’ dots command, then you'll 
probably advance the paper by changing the line spacing. If you do, set it back to either 6 or 8 
lpi (depending on Preferences) when you are finished printing. 

e set bidirectional mode if you selected unidirectional mode in render Case 0. 


set black text; some printers print the text in the last color used, even if it was in graphics mode. 
e restore the margins if you cancelled the margins in render Case 0. 
e any other command needed to exit the graphics mode, eject the page, etc. 


Either PDERR_NOERR or the error from PWrite() should be returned after this call. 


Switching to the next color (Case 6) 


This call provides support for printers which require that colors be sent in separate passes. When 
this call is made, you should instruct the printer to advance its color panel. This case is only needed 
for printers of the type PCC_MULTLPASS, such as the CalComp ColorMaster. 


Transfer() 


Transfer() dithers and renders an entire row of pixels passed to it by the Render() function. When 
Transfer() gets called, it is passed 5 parameters 


Parameters: Pinfo — a pointer to a PrtInfo structure 
y — the row number 
ptr — a pointer to the buffer 
colors — a pointer to the color buffers 
BufOffset — the buffer offset for interleaved printing. 


The dithering process of Transfer() might entail thresholding, grey-scale dithering, or color- 
dithering each destination pixel. 


If PInfo->pi_threshold is non-zero, then the dither value is: 


PInfo->pi_threshold “15. 


206 Amiga ROM Kernel Reference Manual: Devices 


If PInfo->pi_threshold is zero, then the dither value is computed by: 


* (PInfo->pi_dmatrix + ((y & 3) * 2) + (x & 3)) 


where x is initialized to PInfo->pi_xpos and is incremented for each of the destination pixels. 
Since the printer device uses a 4x4 dither matrix, you must calculate the dither value exactly as 
given above. Otherwise, your driver will be non-standard and the results will be unpredictable. 


The Transfer() function renders by putting a pixel in the print buffer based on the dither value. If 
the intensity value for the pixel is greater than the dither value as computed above, then the pixel 
should be put in the print buffer. If it is less than, or equal to the dither value, it should be skipped 


to process the next pixel. 


Printer 
ColorClass 


PCC_BW 


PCC_YMC 


PCC_YMCB 


PCC_YMC_BW 


Type of 
Dithering 


Thresholding 
Grey Scale 
Color 


Thresholding 


Grey Scale 


Color 


Thresholding 
Grey Scale 


Color 


Thresholding 
Grey Scale 


Color 


Rendering logic 


Test the black value against the threshold value to see 
if you should render a black pixel. 
Test the black value against the dither value to see if 


you should render a black pixel. 
NA 


Test the black value against the threshold value to 
see if you should render a black pixel. Print yellow, 
magenta and cyan pixel to make black. 

Test the black value against the dither value to see if 
you should render a black pixel. Print yellow, magenta 
and cyan pixel to make black. 

Test the yellow value against the dither value to see if 
you should render a yellow pixel. Repeat this process 
for magenta and cyan. 


Test the black value against the threshold value to see 
if you should render a black pixel. 

Test the black value against the dither value to see if 
you should render a black pixel. 

Test the black value against the dither value to see 
if you should render a black pixel. If black is not 
rendered, then test the yellow value against the dither 
value to see if you should render a yellow pixel. Re- 
peat this process for magenta and cyan. (See the 
EpsonX transfer.c file) 


Test the black value against the threshold value to see 
if you should render a black pixel. 

Test the black value against the dither value to see if 
you should render a black pixel. 

Test the yellow value against the dither value to see if 
you should render a yellow pixel. Repeat this process 
for magenta and cyan. 


Printer Device 207 


In general, if black is rendered for a specific printer dot, then the YMC values should be ignored, 
since the combination of YMC is black. It is recommended that the printer buffer be constructed 
so that the order of colors printed is yellow, magenta, cyan and black, to prevent smudging and 
minimize color contamination on ribbon color printers. 


The example transfer.c files are provided in C for demonstration only. Writing this module in 
assembler can cut the time needed for a graphic dump in half. The EpsonX transfer.asm file is an 
example of this. 


SetDensity() 


SetDensity() is a short function which implements multiple densities. It is called in the Pre-master 
initialization case of the Render() function. It is passed the density code in density_code. This 
is used to select the desired density or, if the user asked for a higher density than is supported, the 
maximum density available. SetDensity() should also handle narrow and wide tractor paper sizes. 


Densities below 80 dpi should not be supported in SetDensity(), so that a minimum of 640 dots 
across for a standard 8.5x11-inch paper is guaranteed. This results in a 1:1 correspondence of dots 
on the printer to dots on the screen in standard screen sizes. The HP LaserJet is an exception to 
this rule. Its minimum density is 75 dpi because the original HP LaserJet had too little memory to 
output a full page at a higher density. 


Printertag.asm 


For a graphic printer the printer-specific values that need to be filled in in printertag.asm are as 
follows: 


MaxXDots 
The maximum number of dots the printer can print across the page. 


MaxYDots 
The maximum number of dots the printer can print down the page. Generally, if the printer 
supports roll or form feed paper, this value should be 0 indicating that there is no limit. If the 
printer has a definite y dots maximum (as a laser printer does), this number should be entered 


here. 
XDotsInch 
The dot density in x (supplied by SetDensity(, if it exists). 
YDotsInch 
The dot density in y (supplied by SetDensity(), if it exists). 
PrinterClass 
The printer class of the printer. 
PPC_BWALPHA black&white alphanumeric, no graphics. 
PPC_BWGFX black&white (only) graphics. 
PPC_COLORALPHA color alphanumeric, no graphics. 
PPC_COLORGFX color (and maybe black&white) graphics. 
ColorClass 
The color class the printer falls into. 
PCC_BW Black& White only 
PCC_YMC Yellow Magenta Cyan only. 


208 Amiga ROM Kernel Reference Manual: Devices 


PCC_YMC_BW Yellow Magenta Cyan or Black& White, but not both 
PCC_YMCB Yellow Magenta Cyan Black 
PCC_WB White& Black only, 0 is BLACK 
PCC_BGR Blue Green Red 
PCC_BGR_WB Blue Green Red or Black& White 
PCC_BGRW Blue Green Red White 
NumRows 


The number of pixel rows printed by one pass of the print head. This number is used by the 
non-printer-specific code to determine when to make a render Case 2 call to you. You have 
to keep this number in mind when determining how big a buffer you’ll need to store one print 
cycle’s worth of data. 


TESTING THE PRINTER DRIVER 


A printer driver should be thoroughly tested before it is released. Though labor intensive, the 
alphanumeric part of a driver can be easily tested. The graphics part is more difficult. Following 
are some recommendations on how to test this part. 


Start with a black and white (threshold 8), grey scale and color dump of the same picture. The color 
dump should be in color, of course. The grey scale dump should be like the color dump, except it 
will consist of patterns of black dots. The black and white dump will have solid black and solid 
white areas. 


Next, do a dump with the DestX and DestY dots set to an even multiple of the XDotsInch and 
YDotsInch for the printer. For example, if the printer has a resolution of 120 x 144 dpi, a 480 x 432 
dump could be done. This should produce a printed picture which covers 4 x 3 inches on paper. If 
the width of the picture is off, then the wrong value for XDotsInch has been put in printertag.asm. 
If the height of the picture is off, the wrong value for YDotsInch is in printertag.asm. 


Do a color dump as wide as the printer can handle with the density set to 7. 


Make sure that the printer doesn’t force graphic dumps to be done within the text margins. This 
can easily be tested by setting the text margins to 30 and SO, the pitch to 10 cpi and then doing a 
graphic dump wider than 2 inches. The dump should be left justified and as wide as you instructed. 
If the dump starts at character position 30 and is cut off at position 50, the driver will have to be 
changed. These changes involve clearing the margins before the dump (Case 0) and restoring the 
margins after the dump (Case 4). An example of this is present in render.c source example listed at 
the end of this chapter. 


The Invisible Setup. Before the graphic dump, some text must be sent to the printer to 
have the printer device initialize the printer. The “text” sent does not have to contain any 
printable characters (i.e., you can send a carriage retum or other control characters). 


As a final test, construct an image with a white background that has objects in it surrounded by 
white space. Dump this as black and white, grey scale and color. This will test the white-space 
stripping or RLE, and the ability of the driver to handle null lines. The white data areas should be 
separated by at least as many lines of white space as the NumRows value in the printertag.asm file. 


Printer Device 209 


Example Printer Driver Source Code 


As an aid in writing printer drivers, source code for two different classes of printers is supplied. 
Both drivers have been successfully generated with Lattice C 5.10 and Lattice Assembler 5.10. The 
example drivers are: 


EpsonX A YMCB, 8 pin, multi-density interleaved printer. 
HP_Laserjet A black&white, multi-density, page-oriented printer. 


All printer drivers use the following include file macros.i for init.asm. 


FOO OI III IO OI III IOI Ok kok kk tok 
* 

- printer device macro definitions 

* 

TOR IO IORI III kk kok kok kkk kk tok 


*aeses= external definition macros ----------------- 3-99 e nn nnn nnn 
XREF_EXE MACRO 
XREF _LVO\1 
ENDM 
XREF_DOS MACRO 
XREF _Lvo\1 
ENDM 
XREF_GFX MACRO 
XREF _LVO\1 
ENDM 
XREF_ITU MACRO 
XREF _LVO\1 
ENDM 
.aee == library dispatch macros --------------- 999 nn renner nnn nen nnn 
CALLEXE MACRO 
CALLLIB _LVO\1 
ENDM 
LINKEXE MACRO 
LINKLIB _LVO\1, SysBase 
ENDM 
LINKDOS MACRO 
LINKLIB _LVO\1, DOSBase 
ENDM 
LINKGFX MACRO 
LINKLIB _LVO\1,_GfxBase 
ENDM 
LINKITU MACRO 
LINKLIB _LVO\1,_IntuitionBase 
ENDM 
EPSONX 


For the EpsonX driver, both the assembly and C version of Transfer() are supplied. In the Makefile 
the (faster) assembly version is used to generate the driver. 


The EpsonX driver can be generated with the following Makefile. 


LC = le:le 

ASM = lc:asm 

CFLAGS = -iINCLUDE: -b0O -d0O -v 
ASMFLAGS = -iINCLUDE: 


210 Amiga ROM Kernel Reference Manual: Devices 


LINK = le:blink 
LIB = lib:lce.lib+tlib:amiga.lib 


OBJ = printertag.otinit.otdata.ot+tdospecial.o+render.ottransfer.otdensity.o 


TARGET = Epsonx 


@$(LC) $(CFLAGS) $* 


$ (TARGET): printertag.o init.o data.o dospecial.o render.o density.o transfer.o 


@$ (LINK) <WITH < 

FROM $ (OBJ) 

TO $ (TARGET) 

LIBRARY $ (LIB) 

pe SC SD VERBOSE MAP $(TARGET) .map H 


init.o: init.asm 
@S(ASM) $(ASMFLAGS) init.asm 


printertag.o: printertag.asm epsonX_rev.i 
@$ (ASM) $(ASMFLAGS) printertag.asm 


transfer.o: transfer.asm 
@$ (ASM) $(ASMFLAGS) transfer.asm 


dospecial.o: dospecial.c 
data.o: data.c 
density.o: density.c 


render.o: render.c 


Epsonx: macros. 


FI RIK II IIIT TOK II ITOK TOT TT IK IK IK IK IK IK IK KI IKK IKKE K KKK KK KK KEKE EK KKKKK KKK 
* 


* printer device macro definitions 
* 


(2222202 22S SeeS ees eee ec Se ese se Sess ses ese esses esses ete se se see se se Ses eee esi 


Resse SS external definition macros --------------------- 9-9-9 
XREF_EXE MACRO 
XREF _LVO\1 
ENDM 
XREF_DOS MACRO 
XREF _LVO\1 
ENDM 
XREF_GFX MACRO 
XREF _LVO\1 
ENDM 
XREF_ITU MACRO 
XREF _LVO\1 
ENDM 
Secs library dispatch macros -----------------------9 9 enn n nnn nnn 
CALLEXE MACRO 
CALLLIB _LVO\1 
ENDM 
LINKEXE MACRO 
LINKLIB _LVO\1,_SysBase 
ENDM 
LINKDOS MACRO 
LINKLIB _LVO\1,_DOSBase 
ENDM 
LINKGFX MACRO 
LINKLIB _LVO\1,_GfxBase 
ENDM 


Printer Device 211 


LINKITU 


MACRO 


LINKLIB _LVO\1, _ IntuitionBase 


ENDM 


Epsonx: printertag.asm 


ROI IOI III IO IOI IO III III III OI III IOI ke 


* 


x printer device dependent code tag 


* 


OI III III III IO III III IO 


SECTION 


*¥------ Included Files 


INCLUDE 
INCLUDE 
INCLUDE 
INCLUDE 


INCLUDE 


oot SoS Imported Names 


XREF 
XREF 
XREF 
XREF 
XREF 
XREF 
XREF 
XREF 
XREF 


Rie sina Exported Names 


XDEF 


printer 


"exec/types.i" 
"exec/nodes.i" 
"“exec/strings.i" 
“epsonX_rev.i" 


"devices/prtbase.i" 


_Init 

_Expunge 

_Open 

_Close 
_CommandTable 
_PrinterSegmentData 
_DoSpecial 

_Render 
_ExtendedCharTable 


_PEDData 


FOO IOI IOI IOI OOOO IOI III IOI OI a oe 


_PEDData: 


printerName: 


MOVEQ 
RTS 
DC.W 
DC.W 


Dc.L 
DC.L 
pc.L 
DC.L 
pc.L 
DC.B 
DC.B 
DcC.B 
DC.B 
DC.W 
Dc.L 
pc.L 
DC.W 
DC.W 
DC.L 
Dc.L 
Dc.L 
Dc.L 
Dc.L 
DS.L 
Dc.L 


dc.b 


END 


#0,D0 ; show error for OpenLibrary () 
VERSION 

REVISION 

printerName 

_Init 

_Expunge 

_ Open 

_Close 

PPC_COLORGFX ;PrinterClass 

PCC_YMCB 3 ColorClass 

136 3 MaxColumns 

10 ; NumCharSets 

8 ; NumRows 

1632 ; MaxXDots 

0 3 MaxYDots 

120 3 XDotsInch 

72 ; YDotsInch 

_CommandTable ; Commands 

_DoSpecial 

_Render 

30 ; Timeout 
_ExtendedCharTable ; 8BitChars 

1 ; PrintMode (reserve space) 
0 ; ptr to char conversion function 


‘Epsonx’ ,0 


212 Amiga ROM Kernel Reference Manual: Devices 


Epsonx: epsonx_rev.| 
VERSION EQU 35 
REVISION EQU 1 
Epsonx: init.asm 
IO IOI III IOI OI IOI RII III aK KK IK 
* 
* printer device functions 
* 
‘kkk kok kkk kok kkk kkk kkk kkk kick kkk kick kk kk ick kok 
SECTION printer 
keen n-- Included Files ----~------------------------------------------- 
INCLUDE "exec/types.i" 
INCLUDE "exec/nodes.i" 
INCLUDE "exec/lists.i" 
INCLUDE "exec/memory.i" 
INCLUDE "exec/ports.i" 
INCLUDE "exec/libraries.i" 
INCLUDE "macros.i" 
Reman Imported Functions ---------------- enn rr rrr 
XREF_EXE CloseLibrary 
XREF_EXE OpenLibrary 
XREF _AbsExecBase 
XREF _PEDData 
Keene Exported Globals ------~--------------------- == 9-5 
XDEF _Init 
XDEF _Expunge 
XDEF _Open 
XDEF _Close 
XDEF _PD 
XDEF _PED 
XDEF _SysBase 
XDEF _DOSBase 
XDEF _GfxBase 
XDEF _IntuitionBase 
HII II IO KKK KK RII I I ITI KIRK IO IIR III KKK KK KKK IK KKK KK KKK KKK KK KEK 
SECTION printer, DATA 
_PD Dc.L 0 
"PED Dc.L 0 
_SysBase DC.L 0 
_DOSBase DC.L 0 
_GfxBase Dc.L 0 
_IntuitionBase DC.L 0 
TK II KKK IK I IK KK IK IT IK KKK KKK KKK KKK KK KKK KKK KKK KKK IK KKK KEKE KK KKKKKKKK KKK 
SECTION printer, CODE 
_Init: 
MOVE.L 4(A7), PD 
LEA _PEDData (PC) , AO 
MOVE.L AQ, PED 
MOVE.L A6,-(A7) 
MOVE.L _AbsExecBase,A6 
MOVE.L A6, SysBase 
* peeccnn open the dos library 
LEA DLName (PC) ,Al 
MOVEQ #0,D0 


CALLEXE OpenLibrary 
MOVE.L DO, DOSBase 
BEQ initDLErr 


Printer Device 213 


. pocccc- open the graphics library 
LEA GLName (PC) ,Al 
MOVEQ #0,D0 
CALLEXE OpenLibrary 
MOVE.L DO, GfxBase 


BEQ initGLErr 
= (mae open the intuition library 
LEA ILName (PC) ,Al 


MOVEQ #0,D0 
CALLEXE OpenLibrary 
MOVE.L DO, IntuitionBase 


BEQ initILErr 
MOVEQ #0,D0 
pdiRts: 
MOVE.L (A7)+,A6 
RTS 
initPAErr: 
MOVE.L _IntuitionBase,Al 
LINKEXE CloseLibrary 
initILErr: 
MOVE.L _GfxBase,Al 
LINKEXE CloseLibrary 
initGLErr: 
MOVE.L _DOSBase,Al 
LINKEXE CloseLibrary 
initDLErr: 
MOVEQ #-1,D0 
BRA.S pdiRts 
ILName: 
DC.B ‘intuition.library’ 
DC.B 0 
DLName: 
DC.B ‘dos. library’ 
DC.B 0 
GLName: 
DC.B ‘graphics.library’ 
DC.B 0 
DS.W 0 
Eo a ie ie en ane ee Se Re aa Lee ee Ce eo ea es ea aa awa eee Se, 
_Expunge: 
MOVE.L _IntuitionBase,Al 
LINKEXE CloseLibrary 
MOVE.L _GfxBase,Al 
LINKEXE CloseLibrary 
MOVE.L _DOSBase,Al 
LINKEXE CloseLibrary 
Reco eeeseoe eee eee eee eS one one ee Se ee eee ee ee ee ee ee Se eee Se Se ee eee, 
Open: 
MOVEQ #0,D0 
RTS 
So eaiiaescoutaw cca se cto see eee wees Se eel tee eee eee eee See So See ee eee 
Close: 
MOVEQ #0,D0 
RTS 
END 


214 Amiga ROM Kernel Reference Manual: Devices 


Epsonx: data.c 


/* 


Data.c table for EpsonX driver. 


/, 


char *CommandTable[]} ={ 


"\375\033@\375",/* 00 
"\377", /* 01 
"\012", /* 02 
"\015\012", /* 03 
"\377", /* 04 
/* 05 
"\0335\033-\376\033F", 
"\0334", /* 0 
"\0335", /* 07 


"\033-\001", /* 08 
"\033-\376", /* 09 


"\033E", /* 10 
"\033E", /* 11 
"\377", /* 12 
"\377", /* 13 
/* 14 
"\033P\022\033W\376", 
/* 15 
"\033M\022\033W\376", 
"\033P", /* 1 
/* 17 
"\017\033P\033W\376", 
"\022", /* 18 


"\033W\001", /* 19 
"\033W\376", /* 20 


"\377", /* 21 
"\377", /* 22 
"\033G", /* 23 
"\033H", /* 24 
"\033x\001", = /* 25 
"\033x\376",  — /* 26 


"\033S\376", 
"\033T", /* 28 


"\033S\001", /* 29 
"\033T", /* 30 
"\033T", /* 31 
"\377", /* 32 


"\377", /* 33 


"\033R\376", /* 34 
"\033R\001", /* 35 
"\033R\002", /* 36 
"\033R\003", /* 37 
"\033R\004", /* 38 
"\033R\005", /* 39 
"\033R\006", /* 40 
"\033R\007", /* 421 
"\033R\010", /* 42 
"\033R\011", /* 43 
"\033R\012", /* 44 


"\033p1", /* 45 
"\033p0", /* 46 
"\377", /* 47 
"\377", /* 48 
"\377", /* 49 
"\377", /* 50 
"\377", /* 51 
"\377", /* 52 
"\377", /* 53 
"\377", /* 54 
"\0330", /* 55 
"\0332", /* 56 
"\033C", /* 57 
"\033N", /* 58 


aRIS reset 

aRIN initialize 
aIND linefeed 
aNEL CRLF 

aRI reverse LF 


aSGRO normal char set 


6 aSGR3 italics on 


aSGR23 italics off 

aSGR4 underline on 

aSGR24 underline off 
aSGR1 boldface on 

aSGR22 boldface off 

aSFC set foreground color 
aSBC set background color 


aSHORPO normal pitch 


aSHORP2 elite on 


6 aSHORP1 elite off 


aSHORP4 condensed fine on 


aSHORP3 condensed fine off 
aSHORP6 enlarge on 
aSHORPS enlarge off 


aDEN6 shadow print on 
aDENS shadow print off 
aDEN4 double strike on 
aDEN3 double strike off 
aDEN2 NLQ on 

aDEN1 NLO off 


aSUS2 superscript on 
aSUS1 superscript off 
aSUS4 subscript on 

aSUS3 subscript off 
aSUSO normalize the line 
aPLU partial line up 
aPLD partial line down 


aFNTO Typeface 
aFNT1 Typeface 
aFNT2 Typeface 
aFNT3 Typeface 
aFNT4 Typeface 
aFNT5 Typeface 
aFNT6 Typeface 
aFNT7 Typeface 
aFNT8 Typeface 
aFNT9 Typeface 
aFNT10 Typeface 10 


WDAIHDUNPBWNHEO 


aPROP2 proportional on 
aPROP1 proportional off 
aPROPO proportional clear 
aTSS set proportional offset 
aJFY5 auto left justify 
aJFY7 auto right justify 
aJFY6 auto full jusitfy 
aJFYO auto jusity off 

aJFY3 letter space 

aJFY1 word fill 


aVERPO 1/8" line spacing 
aVERP1 1/6" line spacing 
aSLPP set form length 
aPERF perf skip n (n > 0) 


Printer Device 215 


"\ 0330", /* 59 aPERFO perf skip off */ 
"\377", /* 60 aLMS set left margin */ 
"\377", /* 61 aRMS set right margin */ 
"\377", /* 62 aTMS set top margin */ 
"\377", /* 63 aBMS set bottom margin */ 
"\377", /* 64 aSTBM set T&B margins */ 
"\377", /* 65 aSLRM set L&R margins */ 
"\377", /* 66 aCAM clear margins */ 
"\377", /* 67 aHTS set horiz tab */ 
"\377", /* 68 aVTS set vert tab */ 
"\377", /* 69 aTBCO clear horiz tab */ 
"\033D\376", /* 70 aTBC3 clear all horiz tabs */ 
"\377", /* 71 aTBCl clear vert tab */ 
"\033B\376", /* 72 aTBC4 clear all vert tabs */ 

/* 73 aTBCALL clear all h & v tabs */ 
"\033D\376\033B\376", 

/* 74 aTBSALL set default tabs */ 
"\033D\010\020\030\040\050\060\070\100\110\120\130\376", 
W\377", /* 75 aEXTEND extended commands */ 
"\377" /* 76 aRAW next ‘’n’ chars are raw x/ 


/* 
For each character from character 160 to character 255, there is 
an entry in this table, which is used to print (or simulate printing of) 
the full Amiga character set. (see AmigaDos Developer’s Manual, pp A-3) 
This table is used only if there is a valid pointer to this table 
in the PEDData table in the printertag.asm file, and the VERSION is 
33 or greater. Otherwise, a default table is used instead. 
To place non-printable characters in this table, you can either enter 
them as in C strings (ie \011, where 011 is an octal number, or as 
\\000 where 000 is any decimal number, from 1 to 3 digits. This is 
usually used to enter a NUL into the array (C has problems with it 
otherwise.), or if you forgot your octal calculator. On retrospect, 
was a poor choice for this function, as you must say \\\\ to enter a 
backslash as a backslash. Live and learn... 


*/ 

char *ExtendedCharTable[] = { 
" Hs /* NBSP*/ 
"\033R\007[(\033R\\0", /* i */ 
"c\010/", /* cl */ 
"\033R\003#\033R\\0", /* L- */ 
"\O33R\005$\033R\\0", /* o */ 
"\O33R\01L0\\\\\033R\\0", /* Y- */ 
wpe, /* | */ 
"\O033R\002@\033R\\0", /* SS */ 
"\O033R\001~\033R\\0", fT 
ton, /* copyright */ 
"\033S\\0a\010_ \033T", /* a_ */ 
neu, /* << x/ 
Heats [* - */ 
nan /* SHY x/ 
wee /* registered trademark */ 
non, /* = */ 
"\033R\001[\033R\\0", /* degrees */ 
"+\010 ", /* + */ 
"\033S\\0002\033T", /* 2 */ 
"\033S\\0003\033T", /* 3 */ 
nee /* ’ */ 
sy", /* u */ 
“pH, /* reverse P */ 
"\033S\\000.\033T", /* * 
om, /* . */ 
"\033S\\0001\033T", /* 1 */ 
"\033R\001 [\033R\\0\010-", /* o */ 
">", /* >> */ 
"\033S\\0001\033T\010-\010\033S\0014\033T", /* 1/4 */ 
"\033S\\0001\033T\010-\010\033S\0012\033T", /* 1/2 */ 
"\033S\\0003\033T\010-\010\033S\0014\033T", /* 3/4 */ 
"\033R\007)] \033R\\0", /* upside down ? */ 


216 Amiga ROM Kernel Reference Manual: Devices 


}e 


"A\010; 

"A\010°", 

"A\0107", 

"A\010-", 
"\033R\002[\033R\\0", 
"\033R\004] \O33R\\0", 
"\O033R\004[\033R\\0", 
"C\010,", 


"E\010> 
"\033R\011@\033R\\0", 
"E\0107", 
"E\010\033R\001~\033R\\0", 
"I\010; 

"I\010y 

"I\0107", 
"I\010\033R\001~\033R\\0", 


"D\010-", 
"\O33R\O007\\\\\033R\\0", 
"0O\010; 

"O\010'", 

"O\0107", 

"O\010-", 
"\O033R\002\\\\\033R\\0", 


"yx, 


"\033R\004\\\\\033R\\0", 
"U\010; 

"U\010/ we 

"U\0107", 
"\033R\002]\033R\\0", 
"y\010’ u 

een 
"\033R\002~\033R\\0", 


"\033R\001@\033R\\0", 
"a\010'", 

"a\0107", 

"a\010~", 
"\033R\002{\033R\\0", 
"\033R\004}\033R\\0", 
"\033R\004{\033R\\0", 
"\O33R\O01\\\\\033R\\0", 


"\033R\001}\033R\\0", 
"\033R\001{\033R\\0", 
"e\0107", 
"e\010\033R\001~\033R\\0", 
"\033R\006~\033R\\0", 
"i\010'°", 

"i\0107°", 
"i\010\033R\001~\033R\\0", 


nq , 
"\033R\007|\033R\\0", 
"\033R\006/\033R\\0", 
"o\010'", 

"o\0107", 

"o\0107", 
"\033R\002|\033R\\0", 
":\010-" 


"\033R\004{\033R\\0", 
"\033R\001|\033R\\0", 
"u\o1lo'™, 

"u\0107", 
"\033R\002}\033R\\0", 
"y\010'", 

Men 


"y\010\033R\001~\033R\\0" 


‘u x/ 


My x/ 
ty */ 
thorn */ 
"y x/ 


Printer Device 217 


Epsonx: dospecial.c 


/* 
DoSpecial for EpsonX driver. 
ef 


#include "exec/types.h" 
#include "devices/printer.h" 
#include "devices/prtbase.h" 


#define LMARG 3 
#define RMARG 6 
#define MARGLEN 8 


#define CONDENSED it 
#define PITCH 9 
#define QUALITY 17 
#define LPI 24 
#define INITLEN 26 


DoSpecial (command, outputBuffer, vline, currentVMI, crlfFlag, Parms) 
char outputBuffer[]; 

UWORD *command; 

BYTE *vline; 

BYTE *currentVMI; 

BYTE *crlfFlag; 

UBYTE Parms[]; 

{ 


extern struct PrinterData *PD; 


int x = 0, y = 0; 


/* 
00-00 \375 wait 
01-03 \0331L set left margin 
04-06 \033Q0q set right margin 
07-07 \375 wait 
*/ 
static char initMarg[MARGLEN+1] = "\375\0331L\033Qq\375"; 
/* 
00-01 \0335 italics off 
02-04 \033-\000 underline off 
05-06 \033F boldface off 
07-07 \022 cancel condensed mode 
08-09 \033P select pica (10 cpi) 
10-12 \033wW\000 enlarge off 
13-14 \033H doublestrike off 
15-17 \033x\000 draft 
18-19 \033T super/sub script off 
20-22 \033p0 proportional off 
23-24 \0332 6 lpi 
25-25 \015 carriage return 
*/ 


static char initThisPrinter[INITLEN+1] = 


"\0335\033-\000\033F\022\033P\033W\000\033H\033x\000\033T\033p0\0332\015"; 


static BYTE ISOcolorTable[10] = {0, 5, 6, 4, 3, 1, 2, 0}; 


if (*command == aRIN) { 
while (x < INITLEN) { 
outputBuffer[x] = initThisPrinter[x]; 
xt++;7 


} 


if (PD->pd_Preferences.PrintQuality == LETTER) { 
outputBuffer(QUALITY] = 1; 
} 


*currentVMI = 36; /* assume 1/6 line spacing (36/216 => 1/6) */ 


if (PD->pd_Preferences.PrintSpacing == EIGHT_LPI) { 
outputBuffer[LPI] = '0'; 
*currentVMI = 27; /* 27/216 => 1/8 */ 

} 


if (PD->pd_Preferences.PrintPitch == ELITE) { 
outputBuffer[(PITCH] = 'M’; 
} 


218 Amiga ROM Kernel Reference Manual: Devices 


else if (PD->pd_Preferences.PrintPitch == FINE) { 
outputBuffer[CONDENSED] = ’\017'; /* condensed */ 
outputBuffer[PITCH] = 'P’; /* pica condensed */ 

} 


Parms[0] = PD->pd_Preferences.PrintLeftMargin; 
Parms[1] = PD->pd_Preferences.PrintRightMargin; 
*command = aSLRM; 

} 

if (*command == aCAM) { /* cancel margins */ 


y = PD->pd_Preferences.PaperSize == W_TRACTOR ? 136 : 80; 
if (PD->pd_Preferences.PrintPitch == PICA) { 
Parms[(1] = (10 * y) / 10; 


else if (PD->pd_Preferences.PrintPite == ELITE) { 
Parms[1] = (12 * y) / 10; 


else { /* fine */ 
Parms[1] = (17 * y) / 10; 


Parms(0) = 1; 
y = 0; 
*command = aSLRM; 


} 


if (*command == aSLRM) { /* set left and right margins */ 
PD->pd_PWaitEnabled = 253; 
if (Parms(0) == 0) { 
initMarg[LMARG] 


0; 


else { 
initMarg [LMARG] 


Parms(0] - 1; 


} 
initMarg(RMARG] = Parms[1]; 
while (y < MARGLEN) { 
outputBuffer[xt+] = initMarg[ytt+]; 


return (x); 


} 


if (*command == aPLU) { 
if (*vline == 0) 
eyvline = 
*command 
return (0); 


{ 
1; 
= aSUS2; 


} 

if (*vline < 0) { 
*vline = 0; 
*command = aSUS3; 
return (0); 


return (-1); 


} 


if (*command == aPLD) { 
if (*vline == 0) 
*vline = -1; 
*command = aSUS4; 
return (0); 


} 

if (*vline > 0) { 
*vline = 0; 
*command = 
return (0); 


aSUS1; 


return (-1); 


} 


if (*command == aSUSO) { 
*vline = 0; 
} 


if (*command == aSUS1) { 
*vline = 0; 
} 


Printer Device 219 


if 


if 


if 


if 


if 


if 


if 


if 


} 


(*command == aSUS2) { 
*vline = 1; 
(*command == aSUS3) { 
*vline = 0; 
(*command == aSUS4) { 


*vline = -1; 


(*command == aVERPO) { 


*currentVMI = 27; 


(*command == aVERP1) { 


*currentVMI = 36; 


(*command == aIND) { /* lf */ 


outputBuffer[x++] = '\033'; 
outputBuffer[xt+] = ’J'; 
outputBuffer[x++] = *currentVMI; 
return (x); 

(*command == aRI) { /* reverse lf */ 
outputBuffer[x++] = ’\033'; 
outputBuffer[x++] = 'j’; 
outputBuffer[xt++] = *currentVMI; 
return (x); 

(*command == aSFC) { 
if (Parms[0] == 39) { 


Parms(0] = 30; /* set defaults */ 


} 
if (Parms[0] > 37) { 

return(0); /* ni or background color change */ 
} 


outputBuffer[xt+] = '\033'; 

outputBuffer[x++] = ’r'; 

outputBuffer[x++] = ISOcolorTable[Parms[0] - 30); 
/* 


Kludge to get this to work on a CBM MPS-1250 which interprets 
'ESCr’ as go into reverse print mode. The ’ESCt’ tells it to 
get out of reverse print mode. The ‘/NULL’ is ignored by the 
CBM_MPS-1250 and required by all Epson printers as the 
terminator for the ’ESCtNULL’ command which means select 


normal char set (which has no effect). 
*/ 


outputBuffer[xt++] = '\033'; 
outputBuffer[xt++] = '’t’; 
outputBuffer[x++] = 0; 


return (x); 


if (*command == aRIS) { 


} 


PD->pd_PWaitEnabled = 253; 


return(0); 


220 Amiga ROM Kernel Reference Manual: Devices 


Epsonx: render.c 
/ * 
*/ 


EpsonX (EX/FX/JX/LX/MX/RX) driver. 


#include <exec/types.h> 
#include <exec/nodes.h> 
#include <exec/lists.h> 
#include <exec/memory.h> 
#include "devices/printer.h" 
#include "devices/prtbase.h" 


#define NUMSTARTCMD 7 /* # of cmd bytes before binary data */ 
#define NUMENDCMD 1 /* # of cmd bytes after binary data */ 
#define NUMTOTALCMD (NUMSTARTCMD + NUMENDCMD) /* total of above */ 
#define NUMLFCMD 4 /* # of cmd bytes for linefeed */ 
#define MAXCOLORBUFS 4 /* max # of color buffers */ 

#define STARTLEN 19 

#define PITCH 1 

#define CONDENSED 2 

#define LMARG 8 

#define RMARG 11 

#define DIREC 15 


static ULONG TwoBufSize; 
static UWORD RowSize, ColorSize, NumColorBufs, dpi_code, spacing; 
static UWORD colorcodes [MAXCOLORBUFS] ; 


Render(ct, x, y, status) 
long ct, x, y, status; 


extern void *AllocMem(), FreeMem(); 


extern struct PrinterData *PD; 
extern struct PrinterExtendedData *PED; 


UBYTE *CompactBuf () ; 
static ULONG BufSize, TotalBufSize, dataoffset; 
static UWORD spacing, colors[MAXCOLORBUFS] ; 


/* 
00-01 \003P set pitch (10 or 12 cpi) 
02-02 \022 set condensed fine (on or off) 
03-05 \033W\000 enlarge off 
06-08 \0331n set left margin ton 
09-11 \0330n set right margin to n 
12-12 \015 carriage return 
13-15 \033U1 set uni-directional mode 
16-18 \033t\000 see kludge note below 
Kludge to get this to work on a CBM _MPS-1250 which interprets 
‘ESCr’ as go into reverse print mode. The ‘ESCt’ tells it to 
get out of reverse print mode. The ‘’NULL’ is ignored by the 
CBM_MPS-1250 and required by all Epson printers as the 
terminator for the ’ESCtNULL’ command which means select 
normal char set (which has no effect). 

af 


static UBYTE StartBuf[STARTLEN+1] = 
"\033P\022\033W\000\0331n\033Qn\015\033U1\033t\000"; 


UBYTE *ptr, *ptrstart; 
int err; 


switch(status) { 
case 0: /* Master Initialization */ 


/* 
et - pointer to IODRPReq structure. 
x - width of printed picture in pixels. 
y - height of printed picture in pixels. 
*/ 


RowSize = x; 

ColorSize = RowSize + NUMTOTALCMD; 

if (PD->pd_Preferences.PrintShade == SHADE_COLOR) { 
NumColorBufs = MAXCOLORBUFS; 
colors[0] = ColorSize * 3; /* Black */ 
colors[1)]) ColorSize * 0; /* Yellow */ 


Printer Device 221 


colors[2] = ColorSize * 1; /* Magenta */ 
colors(3] = ColorSize * 2; /* Cyan */ 
colorcodes[0] 4; /* Yellow */ 
colorcodes[1] 1; /* Magenta */ 
colorcodes[2] 2; /* Cyan */ 

colorcodes [3] 0; /* Black */ 


ound 


else { /* grey-scale or black&white */ 
NumColorBufs = 1; 
colors[0] = ColorSize * 0; /* Black */ 
colorcodes[0] = 0; /* Black */ 
} 
BufSize = ColorSize * NumColorBufs + NUMLFCMD; 
if (PED->ped_YDotsInch == 216) { 
TwoBufSize = BufSize * 3; 
TotalBufSize = BufSize * 6; 


} 

else if (PED->ped_YDotsInch == 144) { 
TwoBufSize = BufSize * 2; 
TotalBufSize = BufSize * 4; 

} 

else { 
TwoBufSize = BufSize * 1; 
TotalBufSize = BufSize * 2; 

} 

PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_ PUBLIC) ; 

if (PD->pd_PrintBuf == NULL) { 
err = PDERR_BUFFERMEMORY; 

} 


else { 
dataoffset = NUMSTARTCMD; 
/* 
This printer prints graphics within its 
text margins. This code makes sure the 
printer is in 10 cpi and then sets the 
left and right margins to their minimum 
and maximum values (respectively). A 
carriage return is sent so that the 
print head is at the leftmost position 
as this printer starts printing from 
the print head’s position. The printer 
is put into unidirectional mode to 
reduce wavy vertical lines. 
uy 
StartBuf[PITCH] = ’P’; /* 10 cpi */ 
StartBuf [CONDENSED] = '\022’; /* off */ 
/* left margin of 1 */ 
StartBuf[LMARG] = 0; 
/* right margin of 80 or 136 */ 
StartBuf(RMARG] = PD->pd_ Preferences. 
PaperSize == W_TRACTOR ? 136 : 80; 
/* uni-directional mode */ 
StartBuf(DIREC] = ‘1’; 
err = (*(PD->pd_PWrite)) (StartBuf, STARTLEN); 
} 
break; 


case 1: /* Scale, Dither and Render */ 
* 


et - pointer to PrtInfo structure. 
x - 0. 
y row # (0 to Height - 1). 


*/ 

Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors, 
BufSize); 

err = PDERR_NOERR; /* all ok */ 

break; 


case 2 : /* Dump Buffer to Printer */ 


/* 

ct - 0. 

x - 0. 

y - # of rows sent (1 to NumRows). 
*/ 


/* white-space strip */ 
ptrstart = &PD->pd_PrintBuf[dataoffset - NUMSTARTCMD]; 


222 Amiga ROM Kernel Reference Manual: Devices 


case 3 


case 4 


if (PED->ped_YDotsInch == 72) { 
/* y range : 1 to 8 */ 
y = y * 3 - spacing; 
ptr = CompactBuf(ptrstart + NUMSTARTCMD, 
ptrstart, y, 1); 
} 
else if (PED->ped_YDotsInch == 144) { 
/* y range : 1 to 16 */ 
ptr = CompactBuf(ptrstart + NUMSTARTCMD, 
ptrstart, 2, 1); 
if (y > 1) { 
ptr = CompactBuf (&PD->pd_PrintBuf[ 
dataoffset + BufSize], 
ptr, y* 3/2 - 2, 0)7 
; } 
else if (PED->ped_YDotsInch == 216) { 
/* y range : 1 to 24 */ 
ptr = CompactBuf(ptrstart + NUMSTARTCMD, 
ptrstart, 1, 1); 
if (y > 1) { 
ptr = CompactBuf (&PD->pd_PrintBuf[ 
dataoffset + BufSize], 
ptr, 1, 0); 


} 
if (y > 2) { 
ptr = CompactBuf (&PD->pd_PrintBuf[ 
dataoffset + BufSize * 2], 
ptr, y - 2, 0); 
} 


} 
err = (*(PD->pd_PWrite)) (ptrstart, ptr - ptrstart); 
if (err == PDERR_NOERR) { 
dataoffset = (dataoffset == NUMSTARTCMD ? 
TwoBufSize : 0) + NUMSTARTCMD; 
} 


break; 


: /* Clear and Init Buffer */ 
* 


/ 
ct - 0. 
x - 0. 
y - 0. 
*/ 


ClearAndInit (&PD->pd_PrintBuf[dataoffset]); 
err = PDERR_NOERR; 
break; 


: /* Close Down */ 
* 


/ 
ct - error code. 
x - io Special flag from IODRPReq. 
y - 0. 


*/ 

err = PDERR NOERR; /* assume all ok */ 

/* if user did not cancel print */ 

if (ct != PDERR_CANCEL) { 
/* restore preferences pitch and margins */ 
if (PD->pd_Preferences.PrintPitch == ELITE) { 

StartBuf[PITCH] = 'M’; /* 12 cpi */ 

} 


else if (PD->pd_Preferences.PrintPitch == FINE) { 
StartBuf [CONDENSED] = ’\017'; /* on */ 

} 

StartBuf[LMARG] = 
PD->pd_Preferences.PrintLeftMargin - 1; 

StartBuf[RMARG] = 


PD->pd_Preferences.PrintRightMargin; 
StartBuf(DIREC] = ‘0’; /* bi-directional */ 
err = (*(PD->pd_PWrite)) (StartBuf, STARTLEN) ; 


} 
(* (PD->pd_PBothReady) ) (); 
if (PD->pd_PrintBuf != NULL) { 
FreeMem(PD->pd_ PrintBuf, TotalBufSize) ; 
} 


break; 


Printer Device 223 


case 5: /* Pre-Master Initialization */ 


/* 
et - 0 or pointer to IODRPReq structure. 
x - io Special flag from IODRPReq. 
y - 0. 


* 
/* kludge for sloppy tractor mechanism */ 


spacing = PD->pd_Preferences.PaperType == SINGLE 
1 


: 0; 


dpi_code = SetDensity(x & SPECIAL DENSITYMASK) ; 


err = PDERR_NOERR; 
break; 


return(err); 


UBYTE *CompactBuf(ptrstart, ptr2start, y, flag) 
UBYTE *ptrstart, *ptr2start; 

long y; 

int flag; /* 0 - not first pass, !0 - first pass */ 
{ 


static int x; 
UBYTE *ptr, *ptr2; 
long ct; 

int i; 


ptr2 = ptr2start; /* where to put the compacted data */ 
if (flag) { 

x = 0; /* flag no transfer required yet */ 
} 


for (ct=0; ct<NumColorBufs; ct++, ptrstart += ColorSize) 
i = RowSize; 
ptr = ptrstart + i - 1; 
while (i > 0 && *ptr == 0) { 
i--; 
ptr--; 
} 


if (i != 0) { /* if data */ 


*(++ptr) = 13; /* <er> */ 


ptr = ptrstart - NUMSTARTCMD; 
*ptr++ = 27; 


*ptrt++ = ‘rr’; 

*ptrt++ = colorcodes[ct]; /* color */ 
*ptrt++ = 27; 

*ptr++ = dpi_code; /* density */ 
*ptr++ = i & Oxff; 

*ptr++ = i >> 8; /* size */ 
i += NUMTOTALCMD; 

if (x != 0) { /* if must transfer data */ 


/* get sre start */ 
ptr = ptrstart - NUMSTARTCMD; 


do { /* transfer and update dest ptr */ 


*ptr2++ = *ptrt+t+; 
} while (--i); 
} 


else { /* no transfer required */ 
ptr2 += i; /* update dest ptr */ 
} 


} 


if (i != RowSize + NUMTOTALCMD) { /* if compacted or 0 */ 
x = 1; /* flag that we need to transfer next time */ 


} 
} 


*ptr2++ = 13; /* cr */ 
*ptr2t+ = 27; 

*ptr2a++ = 'J'; 

*ptr2++ = y; /* y/216 lf */ 


return (ptr2); 


224 Amiga ROM Kernel Reference Manual: Devices 


ClearAndInit (ptr) 
UBYTE *ptr; 
{ 


ULONG *lptr, i, j; 


/* 
Note : Since ‘NUMTOTALCMD + NUMLFCMD’ is > 3 bytes if is safe 
to do the following to speed things up. 

*/ 

i = TwoBufSize - NUMTOTALCMD - NUMLFCMD; 

j = (ULONG) ptr; 

if (!'(j & 1)) { /* if on a word boundary, clear by longs */ 
i= (i + 3) / 4; 


lptr = (ULONG *) ptr; 
do { 
*lptr++ = 0; 
} while (--i); 
else { /* clear by bytes */ 
do { 
*ptr++ = 0; 
} while (--i); 


return(0); 


Epsonx: transfer.asm 


Pe Se SSS SSSSASESSSSRE SESS SLES SLES SESS SLES ESS SSA SESS SSE SSS SEES ESE SES SES SS 
* 


* Transfer routine for EpsonX 
* 


FESS SSSESESSSSLESSLE SSE SESS SSS ESS SESS SESE S SSS ESE S ESS SESS SESS ESSE SSS SESS 


INCLUDE "exec/types.i" 
INCLUDE "intuition/intuition.i" 
INCLUDE "devices/printer.i" 
INCLUDE "devices/prtbase.i" 
INCLUDE "devices/prtgfx.i" 
XREF  _PD 
XREF PED 
XREF _LVODebug 
XREF _AbsExecBase 
XDEF _Transfer 
SECTION printer, CODE 
_Transfer: 
; Transfer(PInfo, y, ptr, colors, BufOffset) 
; struct PrtInfo *PInfo 4-7 
7; UWORD y; 8-11 
; UBYTE *ptr; 12-15 
; UWORD *colors; 16-19 
; ULONG BufOffset 20-23 


movem.1 


movea.1 
move.1 
movea.1 
movea.1 
move.1 


move.1 
moveq.1 
and.w 
lsl.w 
movea.1 
adda.1l 


movea.1 
cmpi.w 
bne.s 


d2-d6/a2-a4,-(sp) 


36(sp),a0 
40 (sp) ,d0o 
44(sp),al 
48 (sp) ,a2 
52(sp),dl 


a0, da3 
#3,da2 
d0,d2 
#2,da2 
pi_dmatrix(a0),a3 
d2,a3 


_PED, a4 
#216,ped_YDotsInch (a4) 
10$ 


;save regs used 

3a0 = PInfo 

7;d0 =y 

val = ptr 

ja2 = colors 

3;a1 = BufOffset 

ssave y 

7042 =y & 3 

7d2 = (y & 3) << 2 
p;a3 = dmatrix 

3a3 = dmatrix + ((y & 3) << 2) 
7;a4 = ptr to PED 
;triple interleaving? 
7no 


Printer Device 225 


108: 


208: 
308: 


Nae Nee 


divu.w #3,d0 


swap.w d0 
mulu.w d0,dl 
swap.w d0 
bra.s 30$ 


empi.w #144,ped_ YDotsInch (a4) 


bne.s 205 
asr.w #1,d0 
btst #0,da3 
bne.s 30$ 


moveq.1 #0,dl1 
move.w d0,d6 
not.b dé 

adda.l dl,al 


movea.l PD,a4 


zy /= 3 

7d0 = y & 3 
;BufOffset *= y % 3 
7d0 = y / 3 


;double interleaving? 
;no, clear BufOffset 

vy /= 2 

;odd pass? 

sno, dont clear BufOffset 


;BufOffset = 0 
7d6 = bit to set 
;ptr += BufOffset 


7a4 = ptr to PD 


cmpi.w #SHADE COLOR, pd Preferencestpf PrintShade (a4) ;color dump? 


bne not_color 


PInfo 

ptr (ptr + BufOffset) 
colors 

dmatrix ptr 


y 
BufOffset 
bit to set 


movem.1 d7/a5-a6,-(sp) 


movea.l al,a4 
movea.l al,a5 
movea.1 al,a6 
adda.w (a2)+,al 
adda.w (a2)+,a4 
adda.w (a2)+,a5 
adda.w (a2)+,a6 


move.l a6,-(sp) 

move.l1 _AbsExecBase, a6 
jsr _LVODebug (a6) 
move.l (sp)+,a6 


movea.l pi _ColorInt (a0),a2 
move.w pi width(a0),width 
move.w pi _xpos(a0),d2 
movea.l pi ScaleX(a0),a0 
move.b d6,d7 


sxptr 

bptr 
ColorInt ptr 
dmatrix ptr 
yptr 

mptr 

cptr 

Black 

x 

dvalue (dmatrix[x & 3]) 
Yellow 


Magenta 

Cyan 

bit to set 

__ loop: 
move.b PCMBLACK(a2),dl1 
move.b PCMYELLOW(a2),d4 
move.b PCMMAGENTA (a2) ,d5 
move.b PCMCYAN(a2),d6 
addq.1 #ce_SIZEOF,a2 
move.w (a0)+,sx 


7;no 


;save regs used 


yal = ptr + colors[0] (bptr) 
7a4 = ptr + colors(1]) (yptr) 
7a5 = ptr + colors[2) (mptr) 
7;a6 = ptr + colors[3] (cptr) 
7a2 = ColorInt ptr 

7;# of pixels to do 

;a2 =x 

7;a0 = ScaleX (sxptr) 

;d7 = bit to set 

7d1l = Black 

704 = Yellow 

7a5 = Magenta 

7d6 = Cyan 


yadvance to next entry 


7# of times to use this pixel 


226 Amiga ROM Kernel Reference Manual: Devices 


csx_loop: 
moveq.1 #3,d3 
and.w d2,da3 
move.b 0(a3,d3.w),d3 


black: 

cmp.b d3,dl 

ble.s yellow 

bset.b d7,0(al,d2.w) 

bra.s csx_end 
yellow: 

cmp.b a3,d4 

ble.s magenta 

bset.b d7,0(a4,d2.w) 
magenta: 

cmp.b a3,d5 

ble.s cyan 

bset.b d7,0(a5,d2.w) 
cyan: 

cmp.b da3,d6 

ble.s csx_end 

bset.b a7,0(a6,d2.w) 
csx_end: 


addq.w #1,d2 
subq.w #1,sx 
bne.s  csx_loop 
subq.w #1,width 
bne.s  cwidth_loop 


movem.1 (sp)+,d7/a5-a6 


bra exit 
not color: 
; a0 - PInfo 
; al - ptr 
7; a2 - colors 
3 a3 - dmatrix ptr 
; dO -y 
7; a6 - bit to set 
adda.w (a2),al 
move.w pi _width(a0),dl 
subq.w #1,d1 
move.w pi_threshold(a0),d3 
beq.s grey scale 
threshold: 
a0 - PInfo 
al ptr 


- dmatrix ptr 
dl - width-1 


Re Ne Me Me Ne Ne 
wp 
Ww 


a3 threshold 
dé bit to set 
eori.b #15,d3 
movea.] pi_ColorInt (a0),a2 
move.w pi xpos(a0),d2 
movea.] pi ScaleX(a0),a0 
adda.w d2,al 
; a0 - sxptr 
7 al - ptr 
7 a2 - ColorInt ptr 
; a3 - dmatrix ptr (NOT USED) 
3; al - width 
; a3 - dvalue 
3; d4 - Black 
3; a5 - sx 
3; d6 - bit to set 


twidth_ loop: 
move.b PCMBLACK (a2) ,d4 


7a3 
3a3 


x &3 
dmatrix[x & 3] 


;render black? 
sno, try yme 
;set black pixel 


;render yellow pixel? 
;no. 
;set yellow pixel 


;render magenta pixel? 
7no. 
;set magenta pixel 


;render cyan pixel? 
;no, skip to next pixel. 
;clear cyan pixel 


pxt+ 
7 8X-- 


;width-- 


;restore regs used 


yal ptr + colors[0] 
7dal width 
sadjust for dbra 


7;d3 = threshold, thresholding? 
7no, grey-scaling 


7;d3 = dvalue 

7a2 = ColorInt ptr 
;d2 =x 

7a0 = ScaleX (sxptr) 
;ptr += x 

7a4 = Black 


Printer Device 227 


addq.1 
move.w 


cmp.b 
ble.s 
subq.w 


tsx_render: 
bset.b 


adda.w 
dbra 
dbra 
bra.s 


tsx_end: 
adda.w 
dbra 
bra.s 


grey scale: 


#ce_SIZEOF,a2 
(a0)+,d5 


d3,d4 
tsx_end 
#1,d5 


d6, (al) 


#1,al 
d5,tsx_render 
d1,twidth_loop 
exit 


d5,al 
dl,twidth_loop 
exit 


; aQ - PInfo 
; al - ptr 
; a3 - dmatrix ptr 
7 dO -y 
7 al - width-1 
7; a6 - bit to set 
movea.l pi ColorInt (a0) ,a2 


move.w pi _xpos(a0),d2 
movea.1] pi ScaleX(a0),a0 
; a0 - sxptr 
; al - ptr 
; a2 - ColorInt ptr 
7; a3 ~ dmatrix ptr 
; al - width 
3; d2-x 
; a3 - dvalue (dmatrix[x & 3]) 
; a4 - Black 
; aS - sx 
7; a6 - bit to set 


gwidth_loop: 
move .b 
addq.1 


move .w 
subq.w 


gsx_loop: 
moveq.1 
and.w 
move.b 


cmp.b 
ble.s 


bset.b 


gsx_end 
addq.w 
dbra 
dbra 


exit: 
movem.1 
moveq.1 
rts 


SX dc.w 
width dc.w 


END 


PCMBLACK (a2) ,d4 
#ce_SIZEOF, a2 


(a0)+,d5 
#1,d5 


#3,0a3 
d2,d3 
0 (a3,d3.w) ,d3 


a3,d4 
gsx_end 


d6,0(al,d2.w) 
#1,d2 


d5,gsx_loop 
d1,gwidth_loop 


(sp) +,d2-d6/a2-a4 
#0,d0 


;advance to next entry 

705 = # of times to use this pixel 
;render this pixel? 

sno, skip to next pixel. 

;adjust for dbra 

;yes, render this pixel sx times 
**(ptr) |= bit; 

;ptrtt+ 

7SX-- 

swidth-- 


;all done 


;ptr += sx 

swidth-- 

7a2 = ColorInt ptr 

;qa2 =x 

;a0 = ScaleX (sxptr) 

704 = Black 

;advance to next entry 
7d5 = # of times to use this pixel 
;adjust for dbra 

sd3 =x & 3 

703 = dmatrix(x & 3] 
;render this pixel? 

;no, skip to next pixel. 
7*(ptr + x) |= bit 

pxtt 

7SX-7- 

swidth-- 

;restore regs used 
;flag all ok 

; goodbye 


228 Amiga ROM Kernel Reference Manual: Devices 


Epsonx: transfer.c 


/* 
*/ 


C-language Transfer routine for EpsonX driver. 


#include <exec/types.h> 
#include <devices/printer.h> 
#include <devices/prtbase.h> 
#include <devices/prtgfx.h> 


Transfer (PInfo, y, ptr, colors, BufOffset) 
struct PrtInfo *PInfo; 


UWORD y; /* row # */ 

UBYTE *ptr; /* ptr to buffer */ 

UWORD *colors; /* indexes to color buffers */ 
ULONG BufOffset; /* used for interleaved printing */ 


{ 


extern struct PrinterData *PD; 
extern struct PrinterExtendedData *PED; 


static UWORD bit _table[8] = {128, 64, 32, 16, 8, 4, 2, 1}; 
union colorEntry *ColorInt; 

UBYTE *bptr, *yptr, *mptr, *cptr, Black, Yellow, Magenta, 
UBYTE *dmatrix, dvalue, threshold; 

UWORD x, width, sx, *sxptr, color, bit, x3; 


/* printer non-specific, MUST DO FOR EVERY PRINTER */ 
x = PInfo->pi_xpos; 

ColorInt = PInfo->pi_ColorInt; 

sxptr = PInfo->pi_Scalex; 

width = PInfo->pi_width; 


/* printer specific */ 
if (PED->ped_YDotsInch == 216) 
{ 
BufOffset *= y % 3; 
y /= 3; 
} 
else if (PED->ped_YDotsInch == 144) 
{ 


BufOffset *= y & 1; 
y /= 2; 


else 
BufOffset = 0; 


} 
bit = bit_tablely & 7]; 


bptr = ptr + colors[0] + BufOffset; 
yptr = ptr + colors[1] + BufOffset; 
mptr = ptr + colors[2] + BufOffset; 
cptr = ptr + colors[3] + BufOffset; 


/* pre-compute threshold; are we thresholding? */ 
if (threshold = PInfo->pi_threshold) 
{ /* thresholding */ 
dvalue = threshold * 15; 
bptr += x; 
do { /* for all source pixels */ 
/* pre-compute intensity values for Black 
Black = ColorInt->colorByte[PCMBLACK] ; 
ColorInt++; 


sx = *sxptrt+; 

do { /* use this pixel ‘sx’ times */ 
if (Black > dvalue) 
{ 


} 


*bptr |= bit; 


Cyan; 


component */ 


bptr++; /* done 1 more printer pixel */ 


} while (--sx); 
} while (--width); 


else 


Printer Device 229 


{ /* not thresholding, pre-compute ptr to dither matrix */ 
dmatrix = PInfo->pi_dmatrix + ((y & 3) << 2); 


if (PD->pd_Preferences.PrintShade 
{ 


do { /* 


} while 
} 
else 
{ /* color */ 
do { /* 


} while 


Epsonx: density.c 


/* 


SHADE _GREYSCALE) 
for all source pixels */ 
/* pre-compute intensity values for Black */ 
Black = ColorInt->colorByte [{PCMBLACK] ; 
ColorInttt; 
sx = *sxptrtt+; 
do { /* use this pixel 'sx’ times */ 
if (Black > dmatrix[x & 3]) 
{ 
*(bptr + x) |= bit; 
x++; /* done 1 more printer pixel */ 
} while (--sx); 
(--width); 


for all source pixels */ 
/* compute intensity values for each color */ 
Black = ColorInt->colorByte[PCMBLACK] ; 
Yellow = ColorInt->colorByte[PCMYELLOW] ; 
Magenta = ColorInt->colorByte [PCMMAGENTA] ; 
Cyan = ColorInt->colorByte[PCMCYAN] ; 
ColorInt++; 
sx = *sxptrt+t+; 
do { /* use this pixel ‘sx’ times */ 

x3 =x >> 3; 

dvalue = dmatrix[x & 3]; 

if (Black > dvalue) 

{ 


} 

else 

{ /* black not rendered */ 
if (Yellow > dvalue) 
{ 


*(bptr + x) |= bit; 


*(yptr + x) |= bit; 
ty (Magenta > dvalue) 
*(mptr + x) |= bit; 
i (Cyan > dvalue) 

*(cptr + x) |= bit; 


} 
} 
++x; /* done 1 more printer pixel */ 


} while (--sx); 
(--width); 


Density module for EpsonX driver. 


af 


#include <exec/types.h> 
#include "devices/printer.h" 
#include "devices/prtbase.h" 


SetDensity (density code) 
ULONG density code; 
{ 


extern struct PrinterData *PD; 


230 Amiga ROM Kernel Reference Manual: Devices 


extern struct PrinterExtendedData *PED; 


/* SPECIAL DENSITY 0 1 2 3 4 5 6 7 */ 
static int XDPI[8] {120, 120, 120, 240, 120, 240, 240, 240}; 
static int YDPI[8] {72, 72, 144, 72, 216, 144, 216, 216}; 
static char codes[8] = {’L’, ‘'L’, 'L’, 'Z2', ‘L’, '2', 2%, '2'}; 


How 


PED->ped_MaxColumns = 
PD->pd_Preferences.PaperSize == W_TRACTOR ? 136 : 80; 
density code /= SPECIAL DENSITY1; 
/* default is 80 chars (8.0 in.), W_TRACTOR is 136 chars (13.6 in.) */ 
PED->ped_MaxXDots = 
(XDPI [density code] * PED->ped MaxColumns) / 10; 
PED->ped_XDotsInch = XDPI [density code]; 
PED->ped YDotsInch = YDPI [density code]; 
if ((PED->ped_YDotsInch = YDPI{density code]) == 216) { 
PED->ped NumRows = 24; 


} 

else if (PED->ped_YDotsInch == 144) { 
PED->ped_NumRows = 16; 

} 


else { 


} 


return ((int)codes[density code]); 


PED->ped_ NumRows = 8; 


HP_Laserjet 


The driver for the HP_LaserJet can be generated with the following Makefile. 


Le = le:le 

ASM = lc:asm 

CFLAGS = -iINCLUDE: -b0 -d0 -v 

ASMFLAGS = -iINCLUDE: 

LINK = le:blink 

LIB = lib:amiga.libtlib:lc.lib 

OBJ = printertag.otinit.ot+tdata.o+dospecial.otrender.ottransfer.otdensity.o 
TARGET = hp_ laserjet 


@$(LC) $(CFLAGS) $* 
$ (TARGET): printertag.o init.o data.o dospecial.o render.o density.o transfer.o 
@$(LINK) <WITH < 
FROM $ (OBJ) 
TO $ (TARGET) 


LIBRARY $ (LIB) 
NODEBUG SC SD VERBOSE MAP $(TARGET).map H 
< 


init.o: init.asm 
@$ (ASM) S(ASMFLAGS) init.asm 


printertag.o: printertag.asm hp_rev.i 
@$ (ASM) $(ASMFLAGS) printertag.asm 


transfer.o: transfer.asm 
@$ (ASM) $(ASMFLAGS) transfer.asm 


dospecial.o: dospecial.c 
data.o: data.c 
density.o: density.c 


render.o: render.c 


Printer Device 231 


HP_Laserjet: macros./ 


Lee SSS 222 22S SSSES SSS SESS SSSESSSSSESESSSSSSSSS ESSE SESS ES ESS SLES ESS SESS SS 
* 

* printer device macro definitions 

* 

[222222222 Se SSSSSaSSESSESSSSS SASS SESE SSSSLSSSAL SE SESELS ESAS SSS SS SESS SSS SSS 


Rasa s = external definition macros -----~----------- nnn nnn nnn nnn 


XREF_EXE MACRO 
XREF _LVO\1 
ENDM 


XREF_DOS MACRO 
XREF _LVO\1 
ENDM 


XREF_GFX MACRO 
XREF _LVO\1 
ENDM 


XREF_ITU MACRO 
XREF _LVO\1 
ENDM 


MeSee5 library dispatch macros ~--------------- 99 -rnr rrr nnn nnn nnn nnn 


CALLEXE MACRO 
CALLLIB _LVO\1 
ENDM 


LINKEXE MACRO 
LINKLIB _LVO\1,_SysBase 
ENDM 


LINKDOS MACRO 
LINKLIB _LVO\1,_DOSBase 
ENDM 


LINKGFX MACRO 
LINKLIB _LVO\1,_GfxBase 
ENDM 


LINKITU MACRO 
LINKLIB _LVO\1,_IntuitionBase 
ENDM 


HP_Laserjet: printertag.asm 


kK ko oo ko kook koko koko kook ok kkk ok 
* 

* printer device dependent code tag 

* 

HI KKK KK KK I KK KKK KK KKK KK KKK KKK KKK KK KKK KK KKK KKK KKK KKK KKK EK 


SECTION printer 
Kann ene Included Files ----------------- +9992 nnn nnn nnn nnn rrr 
INCLUDE “exec/types.i" 
INCLUDE "exec/nodes.i" 
INCLUDE "exec/strings.i" 
INCLUDE "hp_rev.i" 
INCLUDE "devices/prtbase.i" 
Rennnnn Imported Names ~~---------- n-ne rrr nnn 
XREF _Init 
XREF _Expunge 
XREF _ Open 


232 Amiga ROM Kernel Reference Manual: Devices 


XREFP _Close 
XREF _CommandTable 
XREF _PrinterSegmentData 
XREF _DoSpecial 
XREF _Render 
XREF _ExtendedCharTable 
XREF _ConvFunc 
i===== Exported Names --------- n-ne nnn nner nnn 
XDEF _PEDData 


LESS RAS ESSLESSESSASSSS SASS ES SS ESE SS SSS ESSE SASS SSSR SSE SESS SESS SS ESE SS SES 


MOVEQ #0,D0 ; show error for OpenLibrary () 
RTS 

DC.W VERSION 

DC.W REVISION 


_PEDData: 

pc.L printerName 

DC.L _Init 

pec.L _Expunge 

pc.L _Open 

Dc.L Close 

DC.B PPc_BWGFX ; PrinterClass 

DC.B PcC_BW 3 ColorClass 

DC.B 0 3 MaxColumns 

DC.B 0 3 NumCharSets 

DC.W 1 3; NumRows 

DC.L 600 ; MaxXDots 

Dc.L 7195 3 MaxYDots 

DC.W 75 3 XDotsInch 

DC.W 75 3 YDotsInch 

DC.L _CommandTable ; Commands 

DC.L _DoSpecial 

pc.L _Render 

DC.L 30 ; Timeout 

Dc.L _ExtendedCharTable ; 8BitChars 

DS.L i ; PrintMode (reserve space) 

Dc.L _ConvFunec 7; ptr to char conversion function 
printerName: 


dc.b ‘HP_LaserJet’,0 


END 


HP_Laserjet: hp_rev.i 


VERSION EQU 35 
REVISION EQU 1 


HP_Laserjet: init.asm 


KKK I KKK KK IK KKK KK KKK KKK KKK KKK KI KK KK KKK KKK KKK IKKE KKK KKK KEK KEK KEKE 
* 

* printer device functions 

* 

KKK KKK KKK KKK KKK KKK KKK KIRK KKK KK KKK KKK KKK KKK KKK KKK KEKE KEK KEK KEKE EKK 


SECTION printer 
Kenn o-- Included Files ----------------------- 399-555 
INCLUDE "exec/types.i" 
INCLUDE "exec/nodes.i" 
INCLUDE "exec/lists.i" 
INCLUDE "exec/memory.i" 
INCLUDE "exec/ports.i" 
INCLUDE "exec/libraries.i" 
INCLUDE "macros.i" 


Printer Device 233 


XREF_EXE 
XREF_EXE 


XREF_ 


XREF 


Imported Functions 


Exported Globals 


CloseLibrary 
OpenLibrary 
_AbsExecBase 


_PEDData 


_Init 

_Expunge 
_Open 

_PD 

_PED 

_SysBase 
_DOSBase 
_GfxBase 
_IntuitionBase 


IOI OI IOI IOI IOI IO ok kkk kkk 


XDEF 
XDEF 
XDEF 
XDEF 
XDEF 
XDEF 
XDEF 
XDEF 
XDEF 
SECTION 

_PD 

“PED 

_SysBase 

_DOSBase 

_GfxBase 

_IntuitionBase 


SECTION 
_Init: 


printer, DATA 
Dc.L 0 
DCc.L 0 
pe.L 0 
pe.L 0 
Dc.L 0 
Dpc.L 0 
HK I KK KK IH KK KKK KK KKK KKK KKK KIKI KKK KKK KIKI KK KKK KKK KKK KKK KEK KKK KKK KEKE K 
printer, CODE 
MOVE.L 4(A7), PD 
LEA _PEDData (PC) , AO 
MOVE.L AO, PED 
MOVE.L A6,-(A7) 
MOVE.L _AbsExecBase,A6 
MOVE.L A6, SysBase 
--- open the dos library 
LEA DLName (PC) ,Al 
MOVEQ #0,D0 


pdiRts: 


initPAErr: 


initILErr: 


initGLErr: 


initDLErr: 


CALLEXE OpenLibrary 
MOVE.L DO, DOSBase 
BEQ initDLErr 
--- open the graphics library 
LEA GLName (PC) ,Al 

MOVEQ #0,D0 

CALLEXE OpenLibrary 

MOVE.L DO, GfxBase 

BEQ initGLErr 


open the intuition library 


LEA ILName (PC) ,Al 
MOVEQ #0,D0 

CALLEXE OpenLibrary 
MOVE.L DO, IntuitionBase 
BEQ initILErr 

MOVEQ #0,D0 

MOVE.L (A7)+,A6 

RTS 

MOVE.L _IntuitionBase,Al 
LINKEXE CloseLibrary 
MOVE.L _GfxBase,Al 
LINKEXE CloseLibrary 
MOVE.L _DOSBase,Al 
LINKEXE CloseLibrary 
MOVEQ  #-1,D0 

BRA.S pdiRts 


234 Amiga ROM Kernel Reference Manual: Devices 


ILName: 
Dc.B 
DC.B 
DLName: 
Dc.B 
Dc.B 
GLName: 
DC.B 
DC.B 
DS.W 
_Expunge: 
MOVE.L 
MOVE.L 
MOVE.L 
* 
Open: 


MOVEQ 
RTS 


END 


HP_LaserJet: data.c 


/* 
*/ 


char *CommandTable[] = { 
"\375\033E\375",/ 


Data.c table for HP LaserJet (Plus and II compatible) driver. 


WNSTT", 
"\012", 
"\015\012", 
"\0336a-1R", 


‘intuition.library’ 
0 


‘dos.library’ 
0 


‘graphics.library’ 


_IntuitionBase, Al 
LINKEXE CloseLibrary 


_GfxBase,Al 
LINKEXE CloseLibrary 


_DOSBase, Al 
LINKEXE CloseLibrary 


#0, 


* 
/* 
/* 
/* 
/* 


* 


"\033&d@\033 (sbs", 


"\033(s1S", 
"\033(sS", 
"\0336dD", 
"\0336d@", 
"\033 (s5B", 
"\033(sB", 
W\3T7%; 

"\377", 


"\033(s10h1T", 
"\033(s12h2T", 
"\033(s10h1T", 
"\033(s15H", 
"\033 (s10H", 
"\377", 
MLE 


"\033(s7B", 
"\033(sB", 
"\033 (s3B", 
"\033 (sB", 
"\377", 
"\377", 


ONIT1" 
BNATTH 
WN S71", 
"\377", 
"\377", 
"\033&a-.5R", 


/* 
/* 
/* 
/* 
/* 
/* 
/* 
/* 


/* 
/* 
/* 
/* 
/* 


bo 


00 
01 
02 
03 
04 


aRIS reset 

aRIN initialize 
aIND linefeed 
aNEL CRLF 

aRI reverse LF 


aSGRO normal char set 


aSGR3 


italics on 


aSGR23 italics off 


aSGR4 


underline on 


aSGR24 underline off 


aSGR1 


boldface on 


aSGR22 boldface off 


aSFC set foreground color 
aSBC set background color 


aSHORPO normal pitch 
aSHORP2 elite on 
aSHORP1 elite off 


aSHORP 4 
aSHORP3 


aSHORP6 enlarge on 
aSHORPS5 enlarge off 


aDEN6 
aDENS 
aDEN4 
aDEN3 
aDEN2 
aDEN1 


aSUS2 
aSUS1 
asus4 
aSUS3 
asuso 


shadow print on 

shadow print off 
double strike on 
double strike off 


NLQ on 
NLOQ off 


superscript on 


superscript off 


subscript on 
subscript off 


normalize the line 


aPLU partial line up 


condensed fine on 
condensed fine off 


Printer Device 235 


"\033=", /* 33 
"\033(s3T", /* 34 
"\033(sOT", /* 35 
"\033(s1T", /* 36 
"\033(s2T", /* 37 
"\033(s4T", /* 38 
"\033(s5T", /* 39 
"\033(s6T", /* 40 
"\033(s7T", /* 41 
"\033(s8T", /* 42 
"\033(s9T", /* 43 
"\033(s10T", /* 44 
"\033(s1P", /* 45 
"\033(sP", /* 46 
"\033(sP", /* 47 
"\377", /* 48 
"\377", /* 49 
"\377", /* 50 
"\377", /* 51 
"\377", /* 52 
"\377", /* 53 
"\377", /* 54 
"\033618D", /* 55 
"\033616D", /* 56 
"\377", /* 57 
"\033611L", /* 58 
"\033e1L", /* 59 
"\377", /* 60 
"\377", /* 61 
"\377", /* 62 
"\377", /* 63 
"\377", /* 64 
"\377", /* 65 
"\0339\015", /* 66 
"\377", /* 67 
"\377", /* 68 
"\377", /* 69 
"\377", /* 70 
"\377", /* 71 
"\377", /* 72 
"\377", /* 73 
"\377", /* 74 
"\377", /* 75 
"\377" /* 76 
}e 
char *ExtendedCharTable[] = { 
* 
uw a a "ens a "o", 
WANE Hom wa man, Re 
Woe oma won, 3, wen, 
ae aye, No", >", wn, 
“AN, MAN, NAM) MAN) mya 
bl aay "Et, aE, "EM", wl 
EDN, SNS, WON. MON, NOM; 
wor, um, Nyt, syn mye, 
Mat, Ham wan wan man, 
Het, Met) Hem) ten, "in, 
na Une "o", No", TG 
Nom, ay mu, mu, my, 


aPLD partial line down 


aFNTO 
aFNT1 
aFNT2 
aFNT3 
aFNT4 
aFNTS 
aFNT6 
aFNT7 


Typeface 
Typeface 
Typeface 
Typeface 
Typeface 
Typeface 
Typeface 
Typeface 
aFNT8 Typeface 
aFNT9 Typeface 
aFNT10 Typeface 10 


WDAINDUNDBWNHEO 


aPROP2 proportional on 
aPROP1 proportional off 
aPROPO proportional clear 
aTSS set proportional offset 
aJFY5 auto left justify 
aJFY7 auto right justify 
aJFY6 auto full jusitfy 
aJFYO auto jusity off 

aJFY3 letter space 

aJFY1 word fill 


aVERPO 1/8" line spacing 
aVERP1 1/6" line spacing 
aSLPP set form length 
aPERF perf skip n (n > 0) 
aPERFO perf skip off 


aLMS 
aRMS 


set left margin 
set right margin 
aTMS set top margin 
aBMS set bottom margin 
aSTBM set T&B margins 
aSLRM set L&R margins 
aCAM clear margins 


aHTS set horiz tab 

aVTS set vert tab 

aTBCO clear horiz tab 

aTBC3 clear all horiz tabs 
aTBCl clear vert tab 

aTBC4 clear all vert tabs 
aTBCALL clear all h & v tabs 
aTBSALL set default tabs 


aEXTEND extended commands 


aRAW next ’n’ chars are raw 
BY ME SN 
MEG MEM NSM 
a MBE, 
EM Ls ND 
"AN, "AN, "CM, 
MIS OMEN ONT, 
AOR, HOR Mah, 
ny", "pM, "BM, 
Rat. ta, 2 ot, 
vegies. A 
Mom, Mot, 1/8, 
"y", "p™, "y"™ 


236 Amiga ROM Kernel Reference Manual: Devices 


ay 
uo "\ 270", W\277", WK273", "\272", W\274", ea, "\27 
"\ 253", Mon, "\371", "\373", me "\ 366", 3 "\260", 
"\263", "\ 376", m2 3M, "\250", "\ 363", "\ 364", "\36 
ee we "\ 372", "\375", "\ 367", "\370", "\365", "\27 
"\241", "\340", "\ 242", "\341", "\ 330", "\320", "\323" 
"\ 243", "\ 334", "\ 244", "\ 245", "\ 346", "\ 345", "\246" 
"\ 343", "\266", #\ 350", "\347", "\ 337", e\35i", "\332" 
"\ 322", W\255", "\355", "\256", "\333", "\261", "\360" 
"\ 310", "\304", "\300", "\342", "\314", "\324", "\327" 
WASL1*, W\ 305", "\301", 315", WV 331", BNS25", "\321" 
"\344", "\267", "\312", WVS06", "\302", "\ 352", "\316" 
"\ 326", "\313", "\ 307", "\303", "\317", "\ 262", "\361" 


HP_Laserjet: dospecial.c 
/* 
DoSpecial for HP_LaserJet driver. 


#include "exec/types.h" 
#include "devices/printer.h" 
#include "devices/prtbase.h" 


#define LPI 7 
#define CPI 15 
#define QUALITY 17 
#define INIT LEN 30 
#define LPP 7 
#define FORM_LEN 11 
#define LEFT MARG 3 
#define RIGHT MARG 7 
#define MARG LEN 12 


DoSpecial (command, outputBuffer, vline, currentVMI, crlfFlag, 
char outputBuffer[]; 

UWORD *command; 

BYTE *vline; 

BYTE *currentVMI; 

BYTE *crlfFlag; 

UBYTE Parms[]; 

{ 


extern struct PrinterData *PD; 


extern struct PrinterExtendedData *PED; 
static UWORD textlength, topmargin; 
int x, y, Jj; 
static char initThisPrinter[INIT_ LEN] = 
"\0336d@\033616D\033 (sOb10h1q0p0s3t0ul2v"; 
static char initForm[FORM_LEN] = "\033&1002e000F"; 
static char initMarg[MARG_LEN] = "\033&a0001000M\015"; 
static char initTMarg[] = "\033&1000e000F"; 
x =ye= 3) = Q; 
if (*command == aRIN) { 
while(x < INIT_LEN) { 
outputBuffer[x] = initThisPrinter[x]; 
xtt+; 


} 
outputBuffer[(x++] = ’\015'; 


if (PD->pd_Preferences.PrintSpacing == EIGHT LPI) 


outputBuffer [LPI] "Br 


} 


if (PD->pd_Preferences.PrintPitch == ELITE) { 
outputBuffer[CPI] = '2'; 


} 
else if (PD->pd_Preferences.PrintPitch == FINE) 


outputBuf fer [CPI] "S's 


} 


Sm, 


2", 

1", 

"\264", 
"\247", 
my 
"\336", 
"\265", 
"\335", 
"-\010:", 
"\357" 


, 
¢ 
. 
, 
, 
. 
c 
e 


Parms) 


{ 


Printer Device 237 


if (PD->pd_Preferences.PrintQuality == LETTER) { 
outputBuffer[QUALITY] = ‘2’; 
} 


j = x; /* set the formlength = textlength, top margin = 2 */ 
textlength = PD->pd_Preferences.PaperLength; 
topmargin = 2; 


while (y < FORM_LEN) { 
outputBuffer[xt+] = initForm[yt++]; 


} 
numberString(textlength, j + LPP, outputBuffer); 


Parms(0] = PD->pd_Preferences.PrintLeftMargin; 
Parms(1] = PD->pd_Preferences.PrintRightMargin; 
*command = aSLRM; 


} 


if (*command == aSLRM) { 
j= x; 
y = 0; 
while(y < MARG LEN) { 
outputBuffer[xt+] = initMarg[yt++]; 
} 


numberString(Parms(0] - 1, j + LEFT _MARG, outputBuffer); 
numberString(Parms[1] - 1, j + RIGHT _MARG, outputBuffer); 
return (x); 


if ((*command == aSUS2) && (*vline == 0)) { 
*command = aPLU; 
*vline = 1; 


return (0); 


if ((*command == aSUS2) && (*vline < 0)) { 
*command = aRI; 
*vline = 1; 
return (0); 


if ((*command == aSUS1) && (*vline > 0)) { 
*command = aPLD; 
*vline = 0; 
return (0); 


if ((*command == aSUS4) && (*vline == 0)) { 
*command = aPLD; 
*vline = -1; 


return (0); 


if ((*command == aSUS4) && (*vline > 0)) { 
*command = aIND; 
*vline = -1; 
return(0); 


if ((*command == aSUS3) && (*vline < 0)) { 
*command = aPLU; 
*vline = 0; 
return (0); 
} 
if (*command == aSUSO) { 
if (*vline > 0) { 
*command = aPLD; 


} 

if (*vline < 0) { 
*command = aPLU; 

} 


*yvline = 0; 


return (0); 
} 


if (*command == aPLU) { 


238 Amiga ROM Kernel Reference Manual: Devices 


(*vline) ++; 
return (0); 


} 


if (*command == aPLD) { 
(*vline) --; 
return (0); 


} 
if (*command == aSTBM) { 
if (Parms[0] == 0) { 
Parms[0] = topmargin; 
else { 
} 


if (Parms[{1] == 0) 
Parms[1] = textlength; 


topmargin = --Parms([0]; 


else { 
textlength=Parms[1]; 


} 
while (x < 11) { 

outputBuffer[x] = initTMarg[x]; 

xtt+; 
} 
numberString(Parms[{0], 3, outputBuffer); 
numberString(Parms{1] - Parms[0], 7, outputBuffer) ; 
return (x) ; 


} 


if (*command == aSLPP) { 
while(x < 11) { 
outputBuffer[x] = initForm[x]; 
xt++; 
} 
/*restore textlength, margin*/ 
numberString(topmargin, 3, outputBuffer); 
numberString(textlength, 7, outputBuffer) ; 
return (x); 


} 


if (*command == aRIS) { 
PD->pd_PWaitEnabled = 253; 
} 


return (0); 


} 


numberString(Param, x, outputBuffer) 
UBYTE Param; 

int x; 

char outputBuffer[]; 

{ 


if (Param > 199) { 
outputBuffer[x++] 
Param -= 200; 


rats 


} 

else if (Param > 99) { 
outputBuffer[x++] = '1'; 
Param -= 100; 


else { 


} 


if (Param > 9) 
outputBuffer[x++] = Param / 10 + '0’; 


outputBuffer[x++] = '0’; /* always return 3 digits */ 


else { 


} 


outputBuffer[x++] = Param % 10 + '0’; 


outputBuffer[x++] 


"0O’; 


Printer Device 239 


ConvFunc(buf, c, flag) 

char *buf, c; 

int flag; /* expand lf into lf/cr flag (O-yes, else no ) */ 
{ 


if (c == ’\014") { /* if formfeed (page eject) */ 
PED->ped_ PrintMode = 0; /* no data to print */ 


return(-1); /* pass all chars back to the printer device */ 


} 


Close (ior) 
struct printerIO *ior; 


if (PED->ped_PrintMode) { /* if data has been printed */ 
(* (PD->pd_PWrite)) ("\014",1); /* eject page */ 
(* (PD->pd_PBothReady)) (); /* wait for it to finish */ 
PED->ped_PrintMode = 0; /* no data to print */ 


return (0); 


HP_Laserjet: render.c 


/* 
*/ 


HP_LaserJet driver. 


#include <exec/types.h> 
#include <exec/nodes.h> 
#include <exec/lists.h> 
#include <exec/memory.h> 
#include <devices/prtbase.h> 
#include <devices/printer.h> 


#define NUMSTARTCMD 7 /* # of cmd bytes before binary data */ 
#define NUMENDCMD 0 /* # of cmd bytes after binary data */ 
#define NUMTOTALCMD (NUMSTARTCMD + NUMENDCMD) /* total of above */ 


extern SetDensity (); 


/* 
00-04 \033610L perf skip mode off 
05-11 \033*t075R set raster graphics resolution (dpi) 
12-16 \033*r0A start raster graphics 

*/ 


char StartCmd(18} = "\033610L\033*t075R\033*r0A"; 


Render (ct, x, y, status) 
long ct, x, y, status; 
{ 
extern void *AllocMem(), FreeMem() ; 


extern struct PrinterData *PD; 
extern struct PrinterExtendedData *PED; 


static UWORD RowSize, BufSize, TotalBufSize, dataoffset; 

static UWORD huns, tens, ones; /* used to program buffer size */ 
UBYTE *ptr, *ptrstart; 

int i, err; 


err=PDERR_NOERR; 
switch(status) { 
case 0 : /* Master Initialization */ 
* 


/ 
et - pointer to IODRPReq structure. 
x - width of printed picture in pixels. 
y - height of printed picture in pixels. 
*/ 
RowSize = (x + 7) / 8; 
BufSize = RowSize + NUMTOTALCMD; 


TotalBufSize = BufSize * 2; 
PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC) ; 
if (PD->pd_PrintBuf == NULL) 

err = PDERR_BUFFERMEMORY; /* no mem */ 


else { 


240 Amiga ROM Kernel Reference Manual: Devices 


case l 


case 2 


case 3 


ptr = PD->pd_PrintBuf; 


*ptr++ = ; 

*ptrt++ = '*'3 

*ptrt++ = 'b’; /* transfer raster graphics */ 
*ptrt++ = huns | /0'; 

*ptrt++ = tens | ’0'; 

*ptr++ = ones | 0’; /* printout width */ 
*ptr = "Wl; /* terminator */ 

ptr = &PD->pd_PrintBuf(BufSize}; 

¥ptrt++ = 27; 

*ptrt+ = '*!; 

*ptrt+ = 'b’; /* transfer raster graphics */ 
*ptrt++ = huns | '0'; 

*ptr++ = tens | '0'; 

*ptr++ = ones | '0'; /* printout width */ 
*ptr = 'W'; /* terminator */ 


dataoffset = NUMSTARTCMD; 


/* perf skip mode off, set dpi, start raster gfx */ 
err = (*(PD->pd_PWrite)) (StartCmd, 17); 
} 
break; 
: /* Scale, Dither and Render */ 
* 
et - pointer to PrtInfo structure. 
x - 0. 
y - row # (0 to Height - 1). 
*/ 
Transfer(ct, y, &PD->pd_PrintBuf[dataoffset]); 
err = PDERR_NOERR; /* all ok */ 
break; 
: /* Dump Buffer to Printer */ 
* 
ct - 0. 
x - 0. 
- # of rows sent (1 to NumRows). 
White-space strip. 
*/ 
i = RowSize; 
ptrstart = &PD->pd_PrintBuf[dataoffset - NUMSTARTCMD] ; 
ptr = ptrstart + NUMSTARTCMD + i - 1; 
while (i > 0 G& *ptr == 0) { 
RG: 
ptr--; 
} 
ptr = ptrstart + 3; /* get ptr to density info */ 
*ptr++ = (huns = i / 100) | '0'; 
*ptrt++ = (i - huns * 100) / 10 | '0°; 
*ptr = i %10 | '0%; /* set printout width */ 
err = (*(PD->pd_PWrite)) (ptrstart, i + NUMTOTALCMD) ; 
if (err == PDERR_NOERR) { 
dataoffset = (dataoffset == NUMSTARTCMD ? 
BufSize : 0) + NUMSTARTCMD; 
break; 
: /* Clear and Init Buffer */ 
/* 
ct - 0. 
x - 0. 
y - 0. 
*/ 
ptr = &PD->pd_PrintBuf [dataoffset] ; 
i = RowSize; 
do { 
*ptr++ = 0; 
} while (--i); 
break; 
case 4 : /* Close Down */ 
/* 
et - error code. 
x - io_Special flag from IODRPReq struct 
- 0. 
*/ z 
err = PDERR_NOERR; /* assume all ok */ 


Printer Device 241 


/* if user did not cancel the print */ 
if (ct != PDERR CANCEL) { 
/* end raster graphics, perf skip mode on */ 
if ((err = (*(PD->pd_PWrite) ) 
("\033*rB\033&11L", 9)) == PDERR_NOERR) { 
/* if want to unload paper */ 
if (!(x & SPECIAL_NOFORMFEED)) { 
/* eject paper */ 
err = (*(PD->pd_PWrite) ) 
("\014", 1); 


in 
flag that there is no alpha data waiting that 
needs a formfeed (since we just did one) 

*/ 

PED->ped_PrintMode = 0; 

/* wait for both buffers to empty */ 

(* (PD->pd_PBothReady) ) (); 

if (PD->pd_PrintBuf != NULL) { 
FreeMem(PD->pd_PrintBuf, TotalBufSize); 

} 


break; 
case 5 : /* Pre-Master Initialization */ 
/* 
ct - 0 or pointer to IODRPReq structure. 
x - io Special flag from IODRPReq struct 
y - 0. 
*/ 


/* select density */ 
SetDensity(x & SPECIAL DENSITYMASK) ; 
break; 


return (err); 


HP_Laserjet: density.c 
/ * 
*/ 


Density module for HP_LaserJet 


#include <exec/types.h> 
#include <devices/printer.h> 
#include <devices/prtbase.h> 


SetDensity (density code) 
ULONG density code; 
{ 


extern struct PrinterData *PD; 
extern struct PrinterExtendedData *PED; 
extern char StartCmd[); 


/* SPECIAL DENSITY 0 1 2 3 4 5 6 7 */ 
static int XDPI(8] = {75, 75, 100, 150, 300, 300, 300, 300}; 
static char codes[8][3] = { 

CLOL OTE ISO 0G 1 Foe Eee te Ol) fee be HOE}, 
C3608 OC} Ary 08 0.08 G30 0}, oe OF Or}, 

}; 


density code /= SPECIAL DENSITY1; 
PED->ped_MaxXDots = XDPI{density_ code] * 8; /* 8 inches */ 


/* default is 10.0, US_LEGAL is 14.0 */ 
PED->ped_MaxYDots = 

PD->pd_Preferences.PaperSize == US LEGAL ? 14 : 10; 
PED->ped_MaxYDots *= XDPI [density code]; 


PED->ped_XDotsInch = PED->ped_YDotsInch = XDPI[density code]; 
StartCmd[8] = codes[density code] [0]; 
StartCmd[9] = codes[density code] [1]; 
StartCmd(10] = codes[density code] [2]; 


242 Amiga ROM Kernel Reference Manual: Devices 


HP_Laserjet transfer.c 


/* 
Example transfer routine for HP_LaserJet driver. 


Transfer() should be written in assembly code for speed 
*/ 


#include <exec/types.h> 
#include <devices/prtgfx.h> 


Transfer (PInfo, y, ptr) 
struct PrtInfo *PInfo; 
UWORD y; /* row # */ 
UBYTE *ptr; /* ptr to buffer */ 
{ 
static UBYTE bit_table[] = {128, 64, 32, 16, 8, 4, 2, 1}; 
UBYTE *dmatrix, Black, dvalue, threshold; 
union colorEntry *ColorInt; 
UWORD x, width, sx, *sxptr, bit; 


/* pre-compute */ 

/* printer non-specific, MUST DO FOR EVERY PRINTER */ 

x = PInfo->pi_xpos; /* get starting x position */ 

ColorInt = PInfo->pi_ColorInt; /* get ptr to color intensities */ 
sxptr = PInfo->pi_Scalex; 

width = PInfo->pi_width; /* get # of source pixels */ 


/* pre-compute threshold; are we thresholding? */ 
if (threshold = PInfo->pi threshold) { /* thresholding */ 
dvalue = threshold * 15; /* yes, so pre-compute dither value */ 
do { /* for all source pixels */ 
/* pre-compute intensity value for Black */ 
Black = ColorInt->colorByte[PCMBLACK] ; 
ColorInt++; /* bump ptr for next time */ 


sx = *sxptrt+t; 


/* dither and render pixel */ 
do { /* use this pixel ‘sx’ times */ 
/* if we should render Black */ 
if (Black > dvalue) { 
/* set bit */ 
*(ptr + (x >> 3)) |= bit_table[x & 7]; 


++x; /* done 1 more printer pixel */ 
} while (--sx); 
} while (--width) ; 


else { /* not thresholding, pre-compute ptr to dither matrix */ 
dmatrix = PInfo->pi_dmatrix + ((y & 3) << 2); 
do { /* for all source pixels */ 
/* pre-compute intensity value for Black */ 
Black = ColorInt->colorByte [PCMBLACK] ; 
ColorInt++; /* bump ptr for next time */ 


sx = *sxptrt+t+; 


/* dither and render pixel */ 
do { /* use this pixel ’sx’ times */ 
/* if we should render Black */ 
if (Black > dmatrix[x & 3]) { 
/* set bit */ 
*(ptr + (x >> 3)) |= bit_table[x & 7]; 


++x; /* done 1 more printer pixel */ 


} while (--sx); 
} while (--width) ; 


Printer Device 243 


HP_Laserjet transfer.asm 


TORII OI IOI IOI II IOI IO III IO OOO III IOI III OI IO Ik 
* 


* Transfer routine for HP_LaserJet 
* 


TRIO IO IOI IO IOI OI III OI III III III IO Ik 


INCLUDE "“exec/types.i" 


INCLUDE “intuition/intuition.i" 
INCLUDE "devices/printer.i" 
INCLUDE "devices/prtbase.i" 
INCLUDE "devices/prtgfx.i" 


XREF _PD 
XDEF _Transfer 
SECTION printer, CODE 

_Transfer: 

; Transfer(PInfo, y, ptr) 

7; struct PrtInfo *PInfo 4-7 

; UWORD y; 8-11 

; UBYTE *ptr; 12-15 
movem.1 d2-d6/a2-a3,- (sp) ;save regs used 
movea.l 32(sp),a0 ;a0 = PInfo 
move.1 36(sp),d0 dQ =y 
movea.1 40(sp),al jal = ptr 
move.w pi _width(a0),d1 7dl = width 
subq.w #1,d1 ;adjust for dbra 
move.w pi _threshold(a0),d3 7;a3 = threshold, thresholding? 
beq.s grey scale 7no, grey-scale 

threshold: 

; a0 - PInfo 

; al - ptr 

7; dO -y 

; al - width 

; a3 - threshold 
eori.b #15,d3 7d3 = dvalue 
movea.1 pi ColorInt (a0),a2 7a2 = ColorInt ptr 
move.w pi _xpos(a0),d2 3;qa2 =x 
movea.1 pi ScaleX(a0),a0 3a0 = ScaleX (sxptr) 

a0 - sxptr 
al - ptr 


a2 - ColorInt ptr 
a3 - dmatrix ptr (NOT USED) 
d0 - byte to set (x >> 3) 


width 
d2 - x 
d3 - dvalue 
d4 - Black 
dS - sx 


Se Ne Ne Ne Ne Se Se Me Se Se Ne 
ray 
' 


dé - bit to set 


twidth_loop: 


move.b PCMBLACK (a2) ,d4 7a4 = Black 
addq.l #ce_SIZEOF,a2 ;advance to next entry 
move.w (a0)+,d5 7d5 = # of times to use this pixel (sx) 
emp.b d3,da4 ;render this pixel? 
ble.s tsx_end sno, skip to next pixel. 
subq.w #1,d5 ;adjust for dbra 
tsx_render: syes, render this pixel sx times 
move.w d2,d0 
lsr.w #3,d0 ;compute byte to set 


move.w d2,d6 


244 Amiga ROM Kernel Reference Manual: Devices 


not.w dé 
bset.b d6,0(al,d0.w) 
addq.w #1,d2 
dbra d5,tsx_render 
dbra di,twidth_loop 
bra.s exit 

tsx_end: 
add.w d5,d2 
dbra d1l,twidth_loop 
bra.s exit 


grey scale: 


; a0 - PInfo 
; al - ptr 
+ do Fe 
3; al - width 
movea.1 pi ColorInt (a0),a2 
moveq.1 #3,d2 
and.w d0,d2 
lsl.w #2,da2 
movea.] pi_dmatrix(a0),a3 
adda.l d2,a3 
move.w pi_xpos(a0),d2 
movea.1 pi_ScaleX(a0),a0 
; aO - sxptr 
3; al - ptr 
; a2 - ColorInt ptr 
3; a3 - dmatrix ptr 
; dO - byte to set (x >> 3) 
; al - width 
; ad2-x 
; Q3 - dvalue (dmatrix[x & 3]) 
; a4 - Black 
; a5 - sx 
; d6 - bit to set 
gwidth_loop: 
move.b PCMBLACK (a2) ,d4 
addq.l1 #ce_SIZEOF,a2 
move.w (a0)+,d5 
subq.w #1,d5 
gsx_loop: 
moveq.1 #3,d3 
and.w d2,da3 
move.b 0(a3,d3.w),d3 
cmp.b a3,d4 
ble.s  gsx_end 
move.w d2,d0 
lsr.w #3,a0 
move.w d2,d6 
not.w dé 
bset.b d6,0(al,d0.w) 
gsx_end 
~ addq.w #1,d2 
dbra d5,gsx_loop 
dbra dl, gwidth_loop 
exit: 


movem.1 (sp)+,d2-d6/a2-a3 
moveq.l1 #0,d0 
rts 


END 


;compute bit to set 
7*(ptr + x >> 3) |= 2 %* x 


pxtt 
7Sx-- 
pwidth-- 
pall done 


7x += sx 

swidth-- 

pa2 = ColorInt ptr 

7a2 =y & 3 

7d2 = (y & 3) << 2 

ya3 = dmatrix 

3a3 = dmatrix + ((y & 3) << 2) 
3;da2 =x 

;a0 = ScaleX (sxptr) 

304 = Black 


;advance to next entry 


705 = # of times to use this pixel (sx) 
sadjust for dbra 


x & 3 
dmatrix[x & 3] 


703 
7a3 


wow 


;render this pixel? 
;no, skip to next pixel. 


;compute byte to set 
;compute bit to set 


7*(ptr + x >> 3) l= 2° x 


pxtt+ 
7SX-- 
pwidth-- 


;restore regs used 
;flag all ok 
7; goodbye 


Printer Device 245 


Additional Information on the Printer Device 


Additional programming information on the printer device can be found in the include files and the 
Autodocs for the printer device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Printer Device Information 


INCLUDES devices/printer.h 
devices/printer.i 
devices/prtbase.h 
devices/prtbase.i 
devices/prtgfx.h 
devices/prigfx.i 


AUTODOCS printer.doc 





Additional printer drivers can be found on Fred Fish Disk #344 under RKMCompanion. 


246 Amiga ROM Kernel Reference Manual: Devices 


chapter eleven 
SCSI DEVICE 


The Small Computer System Interface (SCSI) hardware of the A3000 and A2091/A590 is controlled 
by the SCSI device. The SCSI device allows an application to send Exec I/O commands and SCSI 
commands to a SCSI peripheral. Common SCSI peripherals include hard drives, streaming tape 
units and CD-ROM drives. 


SCSI Device 247 


SCSI Device Commands and Functions 


SCSIDeviceCommand Operation 


HD_SCSICMD Issue a SCSI-direct command to a SCSI unit. 


Trackdisk Device Commands Supported by the SCSI Device 


TD_CHANGESTATE __ Retum the disk present/not-present status of a drive. 


TD_FORMAT Initialize one or more tracks with a data buffer. 
TD_PROTSTATUS Retum the write-protect status of a disk. 
TD_SEEK Move the head to a specific track. 


Exec Commands Supported by SCSI Device 


CMD_READ Read one or more sectors from a disk. 

CMD_START Restart a SCSI unit that was previously stopped with CMD_STOP. 
CMD_STOP Stop a SCSI unit. 

CMD_WRITE Write one or more sectors to a disk. 


Exec Functions as Used in This Chapter 


AbortIOQ Abort an I/O request to the SCSI device. 

AllocMem() Allocate a block of memory. 

AllocSignal() Allocate a signal bit. 

CheckIOQ Retum the status of an I/O request. 

CloseDevice() Relinquish use of the SCSI device. All requests must be complete 
before closing. 

DoIO(Q Initiate a command and wait for completion (synchronous request). 

FreeMem() Free a block of previously allocated memory. 

FreeSignal() Free a previously allocated signal. 

OpenDevice() Obtain use of the SCSI device. You specify the type of unit and its 
characteristics in the call to OpenDevice(). 

WaitlOQ Wait for completion of an I/O request and remove it from the reply 
port. 


Exec Support Functions as Used in This Chapter 


CreateExtIO Create an extended IORequest structure for use in communicating 
with the SCSI device. 

CreatePort() Create a message port for reply messages from the SCSI device. Exec 
will signal a task when a message arrives at the port. 

DeleteExtIOQ Delete the extended [ORequest structure created by CreateExtIO(. 

DeletePort() Delete the message port created by CreatePort(). 


248 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The SCSI device operates like other Amiga devices. To use it, you must first open the SCSI device, 
then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga System 
Devices” chapter for general information on device usage. 


The power of the SCSI device comes from its special facility for passing SCSI and SCSI-2 command 
blocks to any SCSI unit on the bus. This facility is commonly called SCS/-direct and it allows the 
Amiga to perform SCSI functions that are “non-standard” in terms of the normal Amiga I/O model. 


To send SCSI-direct or other commands to the SCSI device, an extended I/O request structure 
named IOStdReq is used. 


struct IOStdReq 
{ 


struct Message io Message; 


struct Device *io Device; /* device node pointer */ 

struct Unit *io Unit; /* unit (driver private) */ 

UWORD io_Command; /* device command */ 

UBYTE io_Flags; 

BYTE io_Error; /* error or warning num */ 

ULONG io_ Actual; /* actual number of bytes transferred */ 
ULONG io_Length; /* requested number bytes transferred*/ 
APTR io_Data; /* points to data area */ 

ULONG io_Offset; /* offset for block structured devices */ 


e 


See the include file exec/io.h for the complete structure definition. 


OPENING THE SCSI DEVICE 


Three primary steps are required to open the SCSI device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an I/O request structure of type IOStdReq. The IOStdReq structure is created by the 
CreateExtIO() function. CreateExtIO will initialize your IOStdReq to point to your reply 
port. 


e Open the SCSI device. Call OpenDevice() passing it the I/O request and the SCSI unit encoded 
in the unit field. 


SCSI unit encoding consists of three decimal digits which refer to the SCSI Target ID (bus address) 
in the 1s digit, the SCSI logical unit (LUN) in the 10s digit, and the controller board in the 100s 
digit. For example: 


SCSI unit Meaning 


6 drive at address 6 

12 LUN 1 on multiple drive controller at address 2 

104 second controller board, address 4 

88 not valid: both logical units and addresses range from 0-7 


SCSI Device 249 


The Commodore 2090/2090A/2091 unit numbers are encoded differently. The SCSI logical unit 
(LUN) is in the 100s digit, and the SCSI Target ID is a permuted 1s digit: Target ID 0-6 maps to 
unit 3-9 (7 is reserved for the controller). 


2090/A/1 unit § Meaning 


3 drive at address 0 
109 drive at address 6, logical unit 1 
1 not valid: this is not a SCSI unit. Perhaps it’s an STS06 unit. 


Some controller boards generate a unique name for the second controller board, instead of imple- 
menting the 100s digit (e.g., the 2090A’s iddisk.device). 


struct MsgPort *SCSIMP; /* Message port pointer */ 
struct IOStdReq *SCSIIO; /* IORequest pointer */ 


/* Create message port */ 
if (!(SCSIMP = CreatePort (NULL, NULL) )) 
cleanexit ("Can’t create message port\n",RETURN FAIL); 


/* Create IORequest */ 

if (!(SCSIIO = CreateExtIO(SCSIMP, sizeof (struct IOStdReq) ))) 
cleanexit ("Can’t create IORequest\n",RETURN_ FAIL); 
/* Open the SCSI device */ 


if (error = OpenDevice ("scsi.device", 6L,SCSIIO, OL) ) 
cleanexit ("Can’t open scsi.device\n",RETURN FAIL); 


In the code above, the SCSI unit at address 6 of logical unit 0 of board 0 is opened. 


CLOSING THE SCSI DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). All I/O requests 
must be complete before calling CloseDevice(). If any requests are still pending, abort them with 
AbortIO(. 


if (!(CheckIO(SCSIIO))) 


AbortIO(SCSIIO) ; /* Ask device to abort any pending requests */ 
} 
WaitIO(SCSIIO); /* Wait for abort, then clean up */ 
CloseDevice (SCSIIO) ; /* Close SCSI device */ 


SCSI-Direct 


SCSI-direct is the facility of the Amiga’s SCSI device interface that allows low-level SCSI com- 
mands to be passed directly to a SCSI unit on the bus. This makes it possible to support the special 
features of tape drives, hard disks and other SCSI equipment that do not fit into the Amiga’s normal 
1/O model. For example, with SCSI-direct, special commands can be sent to hard drives to modify 
various drive parameters that are normally inaccessible or which differ from drive to drive. 


In order to use SCSI-direct, you must first open the SCSI device for the unit you want to use in the 
manner described above. You then send an HD_SCSICMD I/O request with a pointer to a SCSI 
command data structure. 


250 Amiga ROM Kernel Reference Manual: Devices 


The SCSI device uses a special data structure for SCSI-direct commands named SCSICmd. 


struct SC 


UWORD 


ULONG 


ULONG 
UBYTE 
UWORD 
UWORD 
UBYTE 
UBYTE 
UBYTE 


UWORD 


UWORD 
}e 


sicmd 
*scsi_Data; /* word aligned data for SCSI Data Phase */ 
/* (optional) data need not be byte aligned */ 
/* (optional) data need not be bus accessible */ 
scsi_Length; /* even length of Data area */ 
/* (optional) data can have odd length */ 
/* (optional) data length can be > 2**24 */ 
scsi_ Actual; /* actual Data used */ 
*scsi_ Command; /* SCSI Command (same options as scsi_ Data) */ 
scsi_CmdLength; /* length of Command */ 
scsi_CmdActual; /* actual Command used */ 
scsi Flags; /* includes intended data direction */ 
scsi_ Status; /* SCSI status of command */ 
*scsi_SenseData; /* sense data: filled if SCSIF_[OLD]AUTOSENSE */ 
/* is set and scsi_Status has CHECK CONDITION */ 
/* (bit 1) set */ 
scsi_SenseLength; /* size of scsi_SenseData, also bytes to */ 
/* request w/ SCSIF_AUTOSENSE, must be 4..255 */ 
scsi_SenseActual; /* amount actually fetched (0 means no sense) */ 


See the include file devices/scsidisk.h for the complete structure definition. 


SCSICmd will contain the SCSI command and any associated data that you wish to pass to the 
SCSI unit. You set its fields to the values required by the unit and the command. When you have 
opened the SCSI device and set the SCSICmd to the proper values, you are ready for SCSI-direct. 


You send a SCSI-direct command by passing an IOStdReq to the SCSI device with a pointer to 
the SCSICmd structure set in io_Data, the size of the SCSICmd structure set in io_Length and 
HD_SCSICMD set in io_Command.: 


struct I0StdReq *SCSIreq = NULL; 


struct SCSICmd Cmd; 


SCSIreq->io_Length 
SCSIreq->io_Data 
SCSIreq->io_Command 


DoIO (SCSI 


(APTR) &Cmd; 
HD_SCSICMD; 


ono 


req); 


/* where the actual SCSI command goes */ 


sizeof (struct SCSICmd) ; 


The SCSICmd structure must be filled in prior to passing it to the SCSI unit. How it is filled in 
depends on the SCSI-direct being passed to the unit. Below is an example of setting up a SCSICmd 
structure for the MODE_SENSE SCSI-direct command. 


UBYTE *bu 


UBYTE Sense(20]; 


struct SC 


ffer; /* a data buffer used for mode sense data */ 


SICmd Cmd; 


/* buffer for request sense data */ 
/* where the actual SCSI command goes */ 


static UBYTE ModeSense[]={ Oxla,0,0xff,0,254,0 }; /* the command being sent */ 


Cmd.scsi_Data = (UWORD *) buffer; 
Cmd.scsi_Length = 254; 


Cmd.scsi_! 


Cmd.scsi_CmdLength = 6; 
Flags = SCSIF_AUTOSENSE | 


SCSIF READ; 


Cmd.scsi_SenseData = (UBYTE *) Sense; 


Cmd.scsi_| 
Cmd.scsi_| 


18; 
0; 


SenseLength 
SenseActual 


where we put mode sense data */ 


how much we will accept 
length of the command 

do automatic REQUEST SENSE 
set expected data direction 
where sense data will go 
how much we will accept 

how much has been received 


Cmd.scsi_Command=(UBYTE *)ModeSense;/* issuing a MODE_SENSE command 


eA 
* 
*/ 
*/ 


SCSI Device 251 


The fields of the SCSICmd are: 


scsi_data 
This field points to the data buffer for the SCSI data phase (if any is expected). It is generally 
the job of the driver software to ensure that the given buffer is DMA-accessible and to drop 
to programmed //O if it isn’t. The filing system provides a stop-gap fix for non-conforming 
drivers with the AddressMask parameter in DEVS:mountlist. For absolute safety, restrict all 
direct reads and writes to Chip RAM. 


scsi_Length 
This is the expected length of data to be transferred. If an unknown amount of data is to be 
transferred from target to host, set the scsi_Length to be larger than the maximum amount of 
data expected. Some controllers explicitly use scsi_Length as the amount of data to transfer. 
The A2091, A590 and A3000 drivers always do programmed I/O for data transfers under 256 
bytes or when the DMA chip doesn’t support the required alignment. 


scsi_Actual 
How much data was actually received from or sent to the SCSI unit in response to the SCSI- 
direct command. 


scsi_Command 
The SCSI-direct command. 


scsi_CmdLength 
The length of the SCSI-direct command in bytes. 


scsi_CmdActual 
The actual number of bytes of the SCSI-direct command that were transferred to the SCSI unit. 


scsi_Flags 
These flags contain the intended data direction for the SCSI command. It is not strictly 
necessary to set the data direction flag since the SCSI protocol will inform the driver which 
direction data transfers will be going. However, some controllers use this information to set up 
DMA before issuing the command . It can also be used as a sanity check in case the data phase 
goes the wrong way. 


One flag in particular, is worth noting. SCSIF_AUTOSENSE is used to make the driver per- 
form an automatic REQUEST SENSE if the target retums CHECK CONDITION for a SCSI 
command. The reason for having the driver do this is the multitasking nature of the Amiga. If 
two tasks were accessing the same drive and the first received a CHECK CONDITION, the sec- 
ond task would destroy the sense information when it sent a command. SCSIF_AUTOSENSE 
prevents the caller from having to make two I/O requests and removes this window of vulner- 
ability. 

scsi_Status 


The status of the SCSI-direct command. The values retumed in this field can be found in the 
SCSI specification. For example, 2 is CHECK_CONDITION. 


scsi_SenseActual 
If the SCSIF_AUTOSENSE flag is set, it is important to initialize this field to zero before issuing 
a SCSI command because some drivers don’t support AUTOSENSE and won’t initialize the 
field. 


252 Amiga ROM Kernel Reference Manual: Devices 


scsi_SenseData 
This field is used only for SCSIF_AUTOSENSE. If a REQUEST SENSE command is directly 
sent to the driver, the data will be deposited in the buffer pointed to by scsi_Data. 


Keep in mind that SCSI-direct is geared toward an initiator role so it can’t be expected to perform 
target-like operations. You can only send commands to a device, not receive them from an initiator. 
There is no provision for SCSI messaging, either. This is due mainly to the interactive nature of the 
extended messages (such as synchronous transfer requests) which have to be handled by the driver 
because it knows the limitations of the controller card and has to be made aware of such protocol 
changes. 


RigidDiskBlock — Fields and Implementation 


The RigidDiskBlock (RDB) standard was bome out of the same development effort as 
HD_SCSICMD and as a result has a heavy bias towards SCSI. However, there is nothing in 
the RDB specification that makes it unusable for devices using other bus protocols. The XT style 
disks used in the A590 also support the RDB standard. 


The RDB scheme was designed to allow the automatic mounting of all partitions on a hard drive 
and subsequent booting from the highest priority partition even if it has a soft loaded filing system. 
Disks can be removed from one controller and plugged into another (supporting the RDB scheme) 
and will carry with it all the necessary information for mounting and booting with them. 


The preferred method of creating RigidDiskBlocks is with the HDToolBox program supplied by 
Commodore. Most controllers include an RDB editor or utility. 


When a driver is initialized, it uses the information contained in the RDB to mount the required 
partitions and mark them as bootable if needed. The driver is also responsible for loading any 
filing systems that are required if they are not already available on the filesystem.resource list. File- 
systems are added to the resource according to DosType and version number. 


The following is a listing of devices/hardblocks.h that describes all the fields in the RDB specifica- 
tion. 


This file describes blocks of data that exist on a hard disk 
to describe that disk. They are not generically accessable to 
the user as they do not appear on any DOS drive. The blocks 
are tagged with a unique identifier, checksummed, and linked 
together. The root of these blocks is the RigidDiskBlock. 


The RigidDiskBlock must exist on the disk within the first 
RDB LOCATION LIMIT blocks. This inhibits the use of the zero 
cylinder in an AmigaDOS partition: although it is strictly 
possible to store the RigidDiskBlock data in the reserved 
area of a partition, this practice is discouraged since the 
reserved blocks of a partition are overwritten by "Format", 
"Install", "DiskCopy", etc. The recommended disk layout, 
then, is to use the first cylinder(s) to store all the drive 
data specified by these blocks: i.e. partition descriptions, 
file system load images, drive bad block maps, spare blocks, 
etc. 


Though only 512 byte blocks are currently supported by the 
file system, this proposal tries to be forward-looking by 
making the block size explicit, and by using only the first 
256 bytes for all blocks but the LoadSeg data. 


* 4% % HH HH HH HH HHH HE HE HE HH HH HOE 


SCSI Device 253 


be ee a a a an ee ee x/ 
/* 
* NOTE 
* optional block addresses below contain $ffffffff to indicate 
. a NULL address, as zero is a valid address 
*/ 
struct RigidDiskBlock 
{ 
ULONG rdb_ID; /* 4 character identifier */ 
ULONG rdb_SummedLongs; /* size of this checksummed structure */ 
LONG rdb_ChkSum; /* block checksum (longword sum to zero) */ 
ULONG rdb_ HostID; /* SCSI Target ID of host */ 
ULONG  rdb_ BlockBytes; /* size of disk blocks */ 
ULONG rdb Flags; /* see below for defines */ 
/* block list heads */ 
ULONG rdb_ BadBlockList; /* optional bad block list */ 
ULONG rdb PartitionList; /* optional first partition block */ 
ULONG rdb FileSysHeaderList; /* optional file system header block */ 
ULONG rdb DrivelInit; /* optional drive-specific init code */ 
/* DriveInit (lun, rdb,ior): "C" stk & d0/a0/al */ 
ULONG rdb Reserved1 [6]; /* set to S$ffffffff */ 


/* physical drive characteristics */ 


ULONG rdb Cylinders; 
ULONG rdb Sectors; 
ULONG rdb_ Heads; 

ULONG rdb_Interleave; 
ULONG rdb_ Park; 

ULONG rdb Reserved2 (3); 
ULONG rdb WritePreComp; 
ULONG rdb ReducedWrite; 
ULONG rdb StepRate; 
ULONG rdb Reserved3(5]; 


number of drive cylinders */ 
sectors per track */ 

number of drive heads */ 
interleave */ 

landing zone cylinder */ 


write precompensation */ 
reduced write current */ 


starting cylinder: 
starting cylinder: 
drive step rate */ 


/* logical drive characteristics */ 


ULONG rdb_RDBBlocksLo; 
ULONG  rdb_RDBBlocksHi; 
ULONG rdb_LoCylinder; 
ULONG rdb_ HiCylinder; 
ULONG rdb CylBlocks; 
ULONG a 

ULONG rdb Reserved4 [2]; 


/* drive identification */ 


/* 
/* 
/* 
/* 
/* 


low block of range reserved for hardblocks */ 
high block of range for these hardblocks */ 
low cylinder of partitionable disk area */ 
high cylinder of partitionable data area */ 
number of blocks available per cylinder */ 


rdb AutoParkSeconds; /* zero for no auto park */ 


char rdb DiskVendor [8]; 

char rdb_DiskProduct [16]; 

char rdb_ DiskRevision[4]; 

char rdb ControllerVendor([8]; 

char rdb ControllerProduct [16]; 

char rdb ControllerRevision[4); 

ULONG rdb Reserved5[10); 
}; 
#define IDNAME RIGIDDISK 0x5244534B /* "RDSK! */ 
#define RDB_LOCATION LIMIT 16 
#define RDBFB LAST 0 /* no disks exist to be configured after */ 
#define RDBFF_LAST 0x01L /* this one on this controller */ 
#define RDBFB LASTLUN L /* no LUNs exist to be configured greater */ 
#define RDBFF_LASTLUN 0x02L /* than this one at this SCSI Target ID */ 
#define RDBFB LASTTID 2 /* no Target IDs exist to be configured */ 
#define RDBFF_LASTTID O0x04L /* greater than this one on this SCSI bus */ 
#define RDBFB NORESELECT 3 /* don’t bother trying to perform reselection */ 
#define RDBFF_NORESELECT 0x08L /* when talking to this drive */ 
#define RDBFB DISKID 4 /* rdb Disk... identification valid */ 
#define RDBFF_DISKID Ox10L 
#define RDBFB CTRLRID 5 /* rdb Controller... identification valid */ 
#define RDBFF_CTRLRID 0x20L a 
[Ri saneat noche owe owe ee ss Sakae oat heehee soe So a case se nese eS */ 
struct BadBlockEntry { 

ULONG bbe BadBlock; /* block number of bad block */ 

ULONG bbe GoodBlock; /* block number of replacement block */ 
i 
struct BadBlockBlock { 

ULONG bbb ID; /* 4 character identifier */ 

ULONG bbb SummedLongs; /* size of this checksummed structure */ 

LONG bbb _ ChkSum; /* block checksum (longword sum to zero) */ 

ULONG bbb _HostID; /* SCSI Target ID of host */ 


254 Amiga ROM Kernel Reference Manual: Devices 


ULONG bbb Next; /* block number of the next BadBlockBlock */ 
ULONG bbb Reserved; 
struct BadBlockEntry bbb_BlockPairs[61); /* bad block entry pairs */ 
/* note [61] assumes 512 byte blocks */ 
he 


#define IDNAME BADBLOCK 0x42414442 /* 'BADB! */ 
/* ewewew nn ww memmewwoeww www moo e www we ew ewww wo www = ww wn on wn www ww ww www */ 
struct PartitionBlock { 
ULONG  pb_ID; /* 4 character identifier */ 
ULONG pb_SummedLongs; /* size of this checksummed structure */ 
LONG pb_ChkSum; /* block checksum (longword sum to zero) */ 
ULONG pb_HostID; /* SCSI Target ID of host */ 
ULONG pb_Next; /* block number of the next PartitionBlock */ 
ULONG pb _ Flags; /* see below for defines */ 
ULONG pb_Reserved1 [2]; 
ULONG pb DevFlags; /* preferred flags for OpenDevice */ 


UBYTE pb_DriveName [32]; /* preferred DOS device name: BSTR form */ 
/* (not used if this name is in use) */ 
ULONG pb_Reserved2[15]; /* filler to 32 longwords */ 
ULONG pb_ Environment [17]; /* environment vector for this partition */ 
ULONG pb_EReserved[15]; /* reserved for future environment vector */ 
he 


#define IDNAME_ PARTITION 0x50415254 /* "PART! */ 
#define PBFB BOOTABLE 0 /* this partition is intended to be bootable */ 
#define PBFF BOOTABLE 1L /* (expected directories and files exist) */ 
#define PBFB NOMOUNT 1 /* do not mount this partition (e.g. manually */ 
#define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */ 
[eesesseesetec ces sstlu lows Se see So ee eee seen cee */ 
struct FileSysHeaderBlock { 
ULONG fhb_ID; /* 4 character identifier */ 
ULONG fhb_SummedLongs; /* size of this checksummed structure */ 
LONG fhb_ChkSum; /* block checksum (longword sum to zero) */ 
ULONG fhb_HostID; /* SCSI Target ID of host */ 
ULONG fhb Next; /* block number of next FileSysHeaderBlock */ 
ULONG fhb Flags; /* see below for defines */ 
ULONG fhb_Reserved1[2]; 
ULONG fhb_DosType; /* file system description: match this with */ 
/* partition environment’s DE_DOSTYPE entry */ 
ULONG fhb_Version; /* release version of this code */ 
ULONG fhb_PatchFlags; /* bits set for those of the following that */ 


/* need to be substituted into a standard */ 
/* device node for this file system: e.g. */ 
/* 0x180 to substitute SegList & GlobalVec */ 


ULONG fhb_Type; /* device node type: zero */ 

ULONG fhb_Task; /* standard dos "task" field: zero */ 

ULONG fhb_ Lock; /* not used for devices: zero */ 

ULONG fhb_Handler; /* filename to loadseg: zero placeholder */ 
ULONG fhb StackSize; /* stacksize to use when starting task */ 
LONG fhb Priority; /* task priority when starting task */ 

LONG fhb_ Startup; /* startup msg: zero placeholder */ 


LONG fhb_SegListBlocks; /* first of linked list of LoadSegBlocks: */ 
/* note that this entry requires some */ 
/* processing before substitution */ 
LONG fhb_GlobalVec; /* BCPL global vector when starting task */ 
ULONG fhb_Reserved2[(23]; /* (those reserved by PatchFlags) */ 
ULONG fhb_Reserved3[(21]; 
e 


#define IDNAME_FILESYSHEADER 0x46534844 /* "FSHD! */ 
Je eee sdas cece bey seh se eos eee cs oS eae cee et on eS */ 
struct LoadSegBlock { 
ULONG lsb_ID; /* 4 character identifier */ 
ULONG lsb_SummedLongs; /* size of this checksummed structure */ 
LONG lsb_ChkSum; /* block checksum (longword sum to zero) */ 
ULONG lsb_HostID; /* SCSI Target ID of host */ 
ULONG lsb Next; /* block number of the next LoadSegBlock */ 


ULONG I1sb LoadData[123]; /* data for "loadseg" */ 
/* note [123] assumes 512 byte blocks */ 
F 


#define IDNAME_LOADSEG 0x4C534547 /* "LSEG? */ 


SCSI Device 255 


HOW A DRIVER USES RDB 


The information contained in the RigidDiskBlock and subsequent PartitionBlocks, et al., is used 
by a driver in the following manner. 


After determining that the target device is a hard disk (using the SCSI-direct command INQUIRY), 
the driver will scan the first RDB_LOCATION_LIMIT (16) blocks looking for a block with the 
“RDSK” identifier and a correct sum-to-zero checksum. If no RDB is found then the driver will give 
up and not attempt to mount any partitions for this unit. If the RDB is found then the driver looks to 
see if there’s a partition list for this unit (rdb_PartitionList). If none, then just the rdb_Flags will 
be used to determine if there are any LUNs or units after this one. This is used for early termination 
of the search for units on bootup. 


If a partition list is present, and the partition blocks have the correct ID and checksum, then for each 
partition block the driver does the following. 


1. Checks the PBFB_NOMOUNT flag. If set then this partition is just reserving space. Skip to 
the next partition without mounting the current one. 


2. If PBFB_NOMOUNT is false, then the partition is to be mounted. The driver fetches the given 
drive name from pb_DriveName. This name will be of the form dh0, work, wb_2.x etc. A 
check is made to see if this name already exists on eb_MountList or DOS’s device list. If 
it does, then the name is algorithmically altered to remove duplicates. The A590, A2091 and 
A3000 append .n (where n is a number) unless another name ending with .n is found. In that 
case the name is changed to .n+1 and the search for duplicates is retried. 


3. Next the driver constructs a parameter packet for MakeDosNode() using the (possibly altered) 
drive name and information about the Exec device name and unit number. MakeDosNode() is 
called to create a DOS device node. MakeDosNode() constructs a filesystem startup message 
from the given information and fills in defaults for the ROM filing system. 


4. If MakeDosNode() succeeds then the driver checks to see if the entry is using a standard 
(“DOS\0”) filing system. If not then the routine for patching in non-standard filing systems is 
called (see “Alien File Systems” below). 


5. Now that the DOS node has been set up and the correct filing system segment has been 
associated with it, the driver checks PBFB_BOOTABLE to see if this partition is marked as 
bootable. If the partition is not bootable, or this is not autoboot time (DiagArea == 0) then 
the driver simply calls AddDosNode() to enqueue the DOS device node. If the partition is 
bootable, then the driver constructs a boot node and enqueues it on eb_MountList using the 
boot priority from the environment vector. If this boot priority is -128 then the partition is not 
considered bootable. 


256 Amiga ROM Kernel Reference Manual: Devices 


ALIEN FILING SYSTEMS 


When a filing system other than the ROM filing system is to be used, the following steps take place. 


1, 


First, open filesystem.resource in preparation for finding the filesystem segment we want. If 
filesystem.resource doesn’t exist then create it and add it via AddResource(). Under 2.0 
the resource is created by the system early on in the initialization sequence. Under pre-V36 
Kickstart, it is the responsibility of the first RDB driver to create it. 


. Scan filesystem.resource looking for a filesystem that matches the DosType and version that 


we want. If it exists go to step 4. 


. Since the driver couldn’t find the filesystem it needed, it will have to load it from the RDB area. 


The list of FileSysHeaderBlocks (pointed to by the “RDSK” block) is scanned for a filesystem 
of the required DosType and version. If none is found then the driver will give up and abort 
the mounting of the partition. If the required filesystem is found, then it is LoadSeg()’ed from 
the “LSEG” blocks and added as a new entry to the filesystem.resource. 


. The SegList pointer of the found or loaded filesystem is held in the FileSysEntry structure 


(which is basically an environment vector for this filing system). Using the patch flags, the 
driver now patches the newly created environment vector (pointed to by the new DosNode) 
using the values in the FileSysEntry being used. This ensures that the partition will have the 
correct filing system set up with the correct mount variables using a shared SegList. 


The eb_Mountlist will now be set up with prioritized bootnodes and maybe some non-bootable, 
but mounted partitions. The system bootstrap will now take over. 


Amiga BootStrap 


At priority -40 in the system module initialization sequence, after most other modules are initialized, 
appropriate expansion boards are configured. Appropriate boards will match a FindConfigDev (, 


-1, 


-1)—these are all boards on the expansion library board list. Furthermore, they will meet all 


of the following conditions: 


1. 


CDB_CONFIGME set in cd_Flags, 


2. ERTB_DIAGVALID set in cd_Rom->er_Type, 
3. 
4 
5 


diagnostic area pointer (in cd_Rom->er_Reserved0c) is non-zero, 


. DAC_CONFIGTIME set in da_Config, and 


. at least one valid resident tag within the diagnostic area, the first of which is used by 


InitResidentQ) below. This resident structure was patched to be valid during the ROM di- 
agnostic routine run when the expansion library first initialized the board. 


SCSI Device 257 


Boards meeting all these conditions are initialized with the standard InitResident() mechanism, with 
a NULL SegList. The board initialization code can find its ConfigDev structure with the expansion 
library’s GetCurrentBinding() function. This is an appropriate time for drivers to Enqueue() a 
boot node on the expansion library’s eb_MountList for use by the strap module below, and clear 
CDB_CONFIGME so a C:BindDrivers command will not try to initialize the board a second time. 


This module will also enqueue nodes for 3.5" trackdisk device units. These nodes will be at the 
following priorities: 





Next, at priority -60 in the system module initialization sequence, the strap module is invoked. 
Nodes from the prioritized eb_MountList list is used in priority order in attempts to boot. An 
item on the list is given a chance to boot via one of two different mechanisms, depending on 
whether it it uses boot code read in off the disk (BootBlock booting), or uses boot code provided 
in the device ConfigDev diagnostic area (BootPoint booting). Floppies always use the BootBlock 
method. Other entries put on the eb_MountList (e.g. hard disk partitions) used the BootPoint 
mechanism for pre-V36 Kickstart, but can use either for V36/V37. 


The eb_MountList is modified before each boot attempt, and then restored and re-modified for the 
next attempt if the boot fails: 


1. The node associated with the current boot attempt is placed at the head of the eb_MountList. 


2. Nodes marked as unusable under AmigaDOS are removed from the list. Nodes that are unusable 
are marked by the longword bn_DeviceNode->dn_Handler having the most significant bit 
set. This is used, for example, to keep UNIX partitions off the AmigaDOS device list when 
booting AmigaDOS instead of UNIX. 


The selection of which of the two different boot mechanisms to use proceeds as follows: 


1. The node must be valid boot node, i.e. meet both of the following conditions: 
a) In_Type is NT_BOOTNODE, 
b) bn_DeviceNode is non-zero, 


2. The type of boot is determined by looking at the DosEnvec pointed to by fssm_Environ 
pointed to by the dn_Startup in the bn_DeviceNode: 
a) if the de_TableSize is less than DE_BOOTBLOCKS, or the de_BootBlocks entry is zero, 
BootPoint booting is specified, otherwise 
b) de_BootBlocks contains the number of blocks to read in from the beginning of the partition, 
checksum, and try to boot from. 


258 Amiga ROM Kernel Reference Manual: Devices 


BOOTBLOCK BOOTING 


In BootBlock booting the sequence of events is as follows: 


1. The disk device must contain valid boot blocks: 

a) the device and unit from dn_Startup opens successfully, 

b) memory is available for the <de_BootBlocks> * <de_SizeBlock> * 4 bytes of boot block 
code, 

c) the device commands CMD_CLEAR, TD_CHANGENUM, and CMD_READ of the boot 
blocks execute without error, 

d) the boot blocks start with the three characters “DOS” and pass the longword checksum 
(with carry wraparound), and 

e) memory is available to construct a boot node on the eb_MountList to describe the floppy. 
If a device error is reported in 1.c., or if memory is not available for 1.b. or l.e., a 
recoverable alert is presented before continuing. 


2. The boot code in the boot blocks is invoked as follows: 
a) The address of the entry point for the boot code is offset BB_ENTRY into the boot blocks 
in memory. 
b) The boot code is invoked with the I/O request used to issue the device commands in 1.c. 
above in register Al, with the io_Offset pointing to the beginning of the partition (the 
origin of the boot blocks) and SysBase in A6. 


3. The boot code returns with results in both DO and AO. 

a) Non-zero DO indicates boot failure. The recoverable alert AN_BootError is presented 
before continuing. 

b) Zero DO indicates AO contains a pointer to the function to complete the boot. This 
completion function is chained to with SysBase in A6 after the strap module frees all its 
resources. It is usually the dos.library initialization function, from the dos.library resident 
tag. Return from this function is identical to return from the strap module itself. 


BOOTPOINT BOOTING 


BootPoint booting follows this sequence: 


1. The eb_MountList node must contain a valid BootPoint: 
a) ConfigDev pointer (in In_Name) is non-zero, 
b) diagnostic area pointer (in cd_Rom er_Reserved0c) is non-zero, 
c) DAC_CONFIGTIME set in da_Config. 


2. The boot routine of a valid boot node is invoked as follows: 
a) The address of the boot routine is calculated from da_BootPoint. 
b) The resulting boot routine is invoked with the ConfigDev pointer on the stack in C fashion 
(..e., (*boot) (configDev) ;). Moreover, register A2 will contain the address of the 
associated eb_MountList node. 


3. Return from the boot routine indicates failure to boot. 


If all entries fail to boot, the user is prompted to put a bootable disk into a floppy drive with the 
“strap screen”. The system floppy drives are polled for new disks. When one appears, the "strap 
screen" is removed and the appropriate boot mechanism is applied as described above. The process 
of prompting and trying continues till a successful boot occurs. 


SCSI Device 259 


SCSI-Direct Example 


/* 
* SCSI Direct.c 
* 
* The following program demonstrates the use of the HD SCSICmd to send a 
* MODE SENSE to a unit on the requested device (default scsi.device). This 
* code can be easily modified to send other commands to the drive. 
* 
* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 
* 
* Run from CLI only 
*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 

#include <devices/scsidisk.h> 
#include <dos/dosextens.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdlib.h> 
#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


#define BUFSIZE 256 


UBYTE *buffer; /* a data buffer used for mode sense data */ 
struct IOStdReq SCSIReq; /* a standard IORequest structure */ 

struct SCSICmd Cmd; /* where the actual SCSI command goes */ 
UBYTE Sense[20]; /* buffer for request sense data */ 

struct MsgPort Port; /* our ReplyPort */ 


void ShowSenseData (void); 


static UBYTE TestReady[] = { 0,0,0,0,0,0 }; /* not used but here for */ 
static UBYTE StartUnit[] = { Oxlb,0,0,0,1,0 }; /* illustration of other */ 
static UBYTE StopUnit[] = { 0x1lb,0,0,0,0,0 }; /* commands. */ 


static UBYTE ModeSense[]={ Oxla,0,0xff,0,254,0 }; /* the command being sent */ 


void main(int argc, char **argv) 
{ 

int unit,tval,i; 

char *dname = "scsi.device"; 
UBYTE *tbuf; 


if ((arge < 2) || (arge > 3)) 
{ 
printf ("Usage: %s unit [xxxx.device]\n",argv[0]); 
exit (100); 
} 
unit = atoi( argv[l] ); 
if (arge == 3) 
dname = argv(2]; 
buffer = (UBYTE *) AllocMem(BUFSIZE, MEMF_PUBLIC|MEMF_CLEAR) ; 
if ('buffer) 
{ 
printf ("Couldn’t get memory\n"); 


exit (100); 
} 


Port.mp Node.ln Pri = 0; /* setup the ReplyPort */ 
Port.mp SigBit = AllocSignal(-1); 
Port.mp SigTask = (struct Task *)FindTask (0); 


NewList ( &(Port.mp MsgList) ); 


260 Amiga ROM Kernel Reference Manual: Devices 


SCSIReq.io Message 


-mn_ReplyPort = &Port; 


if (OpenDevice( dname, unit, &SCSIReq, 0)) 
{ 


printf ("Couldn’t open unit %ld on %s\n",unit,dname) ; 
FreeMem( buffer,BUFSIZE ); 


exit (100); 
} 


SCSIReq.io Length 
SCSIReq.io Data 


sizeof (struct SCSICmd); 
(APTR) &Cmd; 


SCSIReq.io_ Command HD_SCSICMD; /* the command we are sending 
Cmd.scsi_Data = (UWORD *) buffer; /* where we put mode sense data 
Cmd.scsi_ Length = 254; /* how much we will accept */ 
Cmd.scsi_CmdLength = 6; /* length of the command */ 


Cmd.scsi_ Flags = SCSIF_AUTOSENSE|SCSIF_READ; 


Cmd.scsi_SenseData 


Cmd.scsi_SenseLength = 18; 
Cmd.scsi_ SenseActual = 0; 


/* do automatic REQUEST SENSE */ 

/* set expected data direction */ 
=(UBYTE *) Sense; /* where sense data will go 
/* how much we will accept 
/* how much has been received 


Cmd.scsi_Command=(UBYTE *)ModeSense;/* issuing a MODE SENSE command 


DoIO( &SCSIReq ); 


/* send it to the device driver 


if (Cmd.scsi_ Status) 
ShowSenseData(); /* if bad status then show it */ 


else 


{ 
printf ("\nBlock descriptor header\n") ; 


printf ("======= 


Seeeeesses=s====\n") > 


printf ("Mode Sense data length = %d\n", (short) buffer[0]); 
printf ("Block descriptor length = %d\n", (short) buffer[3]); 
tbuf = &buffer[4]; 


printf ("Density code d\n", (short) tbuf[0]); 
tval = (tbuf[1])<<16) + (tbuf [2] <<8) + tbuf [3]; 

printf ("Number of blocks = $ld\n",tval); 

tval = (tbuf[5]<<16) + (tbuf[6]<<8) + ‘ebuf [7]; 

printf ("Block size = %$ld\n",tval); 

tbuf += buffer[3]; /* move to page descriptors */ 


while ((tbuf - 
{ 


buffer) < buffer[0]) 


switch (tbuf(0] & Ox7f) 
{ 


case 1: 
printf("\nError Recovery Parameters\n"); 
printf ("====s=s====s===s=============\n"); 
printf ("Page length 
printf ("DISABLE CORRECTION 
printf ("DISABLE XFER ON ERROR 
printf ("POST ERROR 
printf ("ENABLE EARLY CORRECTION 
printf ("READ CONTINUOUS 
printf ("TRANSFER BLOCK 
printf ("AUTO READ REALLOCATION 
printf ("AUTO WRITE REALLOCATION 
printf ("Retry count 
printf ("Correction span 
printf ("Head offset count 
printf ("Data strobe offset count 
printf ("Recovery time limit 


mirduur th ounbu waved 


tbhuf += tbuf[1]+2; 


break; 

case 2: 
printf ("\nDisconnect/Reconnect Control\n") ; 
printf ("s=========s=<==sss=s=s==s=s======\n"); 


printf ("Page length 


*/ 
*/ 


*/ 
*/ 
*/ 


*/ 
*/ 


d\n", (short) tbuf[1]); 

d\n", (short) tbuf [2] &1) 

d\n", (short) (tbuf [2] >21) &1); 
$d\n", (short) (tbuf[(2] >>2) 6&1); 
d\n", (short) (tbuf[{2] >>3) 6&1); 
d\n", (short) (tbuf[(2] >>4) 6&1); 
d\n", (short) (tbuf(2] >>5) «1); 
d\n", (short) (tbuf(2] >>6) «1); 
$d\n", (short) (tbuf[2] >>7)&1); 
$d\n", (short) tbuf [3] 
$da\n", (short) tbuf [4 
$d\n", (short) tbuf [5 
$da\n", (short) tbuf [6 
d\n", (short) tbuf [7 


3 
)); 
]); 
1); 
]); 


d\n", (short) tbuf [ 


= 1)); 
printf("Buffer full ratio = $d\n", (short)tbuf[2]); 
= 3)); 


printf ("Buffer empty ratio 


$d\n", (short) tbuf [ 


SCSI Device 261 


tval = (tbuf[4] <<<8)+tbuf [5]; 
printf("Bus inactivity limit 
tval = (tbuf[6] <<<8)+tbuf[7]; 
printf("Disconnect time limit 
tval = (tbuf[8] <<<8)+tbuf [9]; 
printf("Connect time limit 

tval = (tbuf[10] <<8)+tbuf([11]; 
printf ("Maximum burst size 
printf("Disable disconnection 


$d\n",tval); 


$d\n",tval); 


$d\n",tval); 


$da\n",tval); 
d\n", (short) tbuf[12]«1); 


tbuf += tbuf[1]+2; 


break; 

case 3: 
printf("\nDevice Format Parameters\n") ; 
printf ("s===s=s=====s=s=s===s========\n") ; 
printf("Page length = $d\n", (short) tbuf[1]); 
tval = (tbuf[2] <<8)+tbuf [3]; 
printf("Tracks per zone = $d\n",tval); 
tval = (tbuf[4)<<8)+tbuf [5]; 
printf("Alternate sectors/zone = %d\n",tval); 
tval = (tbuf[6]<<8)+tbuf[7]; 
printf ("Alternate tracks/zone = $d\n",tval); 
tval = (tbuf[8] <<<8)+tbuf [9]; 
printf("Alternate tracks/volume = %d\n",tval); 
tval = (tbuf[10]<<8)+tbuf[11]; 
printf("Sectors per track = $d\n",tval); 
tval = (tbuf[(12] <<<8)+tbuf [13]; 
printf ("Bytes per sector = $d\n",tval); 
tval = (tbuf[14] <<8)+tbuf[15]; 
printf ("Interleave = %d\n",tval); 
tval = (tbuf[16] <<<8)+tbuf[17]; 
printf ("Track skew factor = $d\n",tval); 
tval = (tbuf[18]<<8)+tbuf [19]; 
printf("Cylinder skew factor = $d\n",tval); 
tbuf += tbuf[1]+2; 
break; 

case 4: 
printf("\nDrive Geometry Parameters\n") ; 
printf (Smeseesesesress=seeseeess==\j") ; 
printf ("Page length = d\n", (short)tbuf[1]); 
tval = (tbuf[2] <<16)+(tbuf [3] <<8)+tbuf [4]; 
printf ("Number of cylinders = $ld\n",tval); 
printf ("Number of heads = d\n", (short)tbuf[5]); 
tval = (tbuf[6]) <<<16)+ (tbuf[6] <<8)+tbuf [8]; 
printf("Start write precomp = $ld\n",tval); 
tval = (buf (9} <<16) + (tbuf [10] <8) #tbut (11) 
printf("Start reduced write $ld\n",tval); 
tval = (tbuf(12] <<8)+tbuf[13]; 
printf("Drive step rate = $d\n",tval); 
tval = (tbuf[14] <<16)+(tbuf[15] <<8)+tbuf(16]; 
printf ("Landing zone cylinder = $ld\n",tval); 
tbuf += tbuf[1]+2; 
break; 

default: 
Dee ee ose Unique Page Code Rar er rere 
printf ("======s===s=s======s==========\n"); 


for (i=0; i<=tbuf[1]+1; i++ ) 
printf("%x ", (short) tbuf[i]); 


printf ("\n"); 
tbuf += tbhuf[1]+2; 
} 
CloseDevice( &SCSIReq ); 
FreeMem( buffer, BUFSIZE ); 


FreeSignal (Port.mp SigBit); 
} 


262 Amiga ROM Kernel Reference Manual: Devices 


void ShowSenseData (void) 
int i; 


for (i=0; i<18; i++) 
printf ("%x ", (int)Sense[i]); 


printf ("\n"); 
} 


Additional Information on the SCSI Device 


Additional programming information on the SCSI device can be found in the include files for the 
SCSI device and RigidDiskBlock. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


For information on the SCSI commands, see either the ANSI-X3T9 (draft SCSI-2) or ANSI X3.131 
(SCSI-1) specification. The NCR SCSI BBS—phone number (316)636-8700 (2400 baud)—has 
electronic copies of the current SCSI specifications. 


SCSI Device Information 


INCLUDES devices/scsidisk.h 


devices/scsidisk.i 
devices/hardblocks.h 
devices/hardblocks.i 





SCSI Device 263 


chapter twelve 
SERIAL DEVICE 


The serial device provides a hardware-independent interface to the Amiga’s built-in RS-232C 
compatible serial port. Serial ports have a wide range of uses, including communication with 
modems, printers, MIDI devices, and other computers. The same device interface can be used for 
additional “byte stream oriented devices”—usually more serial ports. The serial device is based on 
the conventions of Exec device I/O, with extensions for parameter setting and control. 


Serial Device Characteristics 


MODES Exclusive 
Shared Access 


BAUD RATES 110-292,000 


HANDSHAKING Three- Wire 
Seven- Wire 





Serial Device 265 


Serial Device Commands and Functions 


Device Command Operation 

CMD_CLEAR Reset the serial port’s read buffer pointers. 

CMD_FLUSH Purge all queued requests for the serial device (does not affect active 
requests). 

CMD_READ Read a stream of characters from the serial port buffer. The number 
of characters can be specified or a termination character(s) used. 

CMD_RESET Reset the serial port to its initialized state. All active and queued I/O 
requests will be aborted and the current buffer will be released. 

CMD_START Restart all paused I/O over the serial port. Also sends an "xON". 

CMD_STOP Pause all active I/O over the serial port. Also sends an "xOFF". 

CMD_WRITE Write out a stream of characters to the serial port. The number of 
characters can be specified or a NULL-terminated string can be sent. 

SDCMD_BREAK Send a break signal out the serial port. May be done immediately or 
queued. Duration of the break (in microseconds) can be set by the 
application. 

SDCMD_QUERY Retum the status of the serial port lines and registers, and the number 


of bytes in the serial port’s read buffer. 
SDCMD_SETPARAMS _ Set the parameters of the serial port. This ranges from baud rate to 
number of microseconds a break will last. 


Exec Functions as Used in This Chapter 


AbortIO() Abort a command to the serial device. If the command is in progress, 
it is stopped immediately. If it is queued, it is removed from the queue. 

BeginIOQ Initiate a command and retum immediately (asynchronous request). 
This is used to minimize the amount of system overhead. 

CheckIOQ Determine the current state of an I/O request. 

CloseDevice() Relinquish use of the serial device. All requests must be complete. 

DolOQ Initiate a command and wait for completion (synchronous request). 

OpenDevice() Obtain use of the serial device. 

SendIOQ Initiate a command and return immediately (asynchronous request). 

WaitIOQ Wait for the completion of an asynchronous request. When the request 


is complete the message will be removed from your reply port. 


Exec Support Functions as Used In This Chapter 


CreateExtIO() Create an extended I/O request structure of type IOExtSer. This 
structure will be used to communicate commands to the serial device. 
CreatePort() Create a signal message port for reply messages from the serial device. 
Exec will signal a task when a message arrives at the port. 
DeleteExtIO() Delete an extended I/O request structure created by CreateExtIO(). 
DeletePort() Delete the message port created by CreatePort(). 


266 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The serial device operates like the other Amiga devices. To use it, you must first open the serial 
device, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
System Devices” chapter for general information on device usage. 


The I/O request used by the serial device is called IOExtSer. 


struct IOExtSer 


{ 
struct IOStdReq I0Ser; 


ULONG io_CtlChar; /* control characters */ 

ULONG io_RBufLen; /* length in bytes of serial read buffer */ 
ULONG io_ExtFlags; /* additional serial flags */ 

ULONG io_Baud; /* baud rate */ 

ULONG 1o_BrkTime; /* duration of break in microseconds */ 
struct iOTArray io _TermArray; /* termination character array */ 
UBYTE io_ReadLen; /* number of bits per read character */ 
UBYTE io WriteLen; /* number of bits per write character */ 


UBYTE io _StopBits; /* number of stopbits for read */ 
UBYTE io_SerFlags; /* serial device flags */ 
UWORD io_ Status; /* status of serial port and lines */ 
}; 


See the include file devices/serial.h for the complete structure definition. 


OPENING THE SERIAL DEVICE 


Three primary steps are required to open the serial device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an extended I/O request structure of type IOExtSer using CreateExtIO(. 
CreateExtIO() will initialize the I/O request to point to your reply port. 


e Open the serial device. Call OpenDevice(), passing the I/O request. 


struct MsgPort *SerialMP; /* Define storage for one pointer */ 
struct IOExtSer *SerialI0; /* Define storage for one pointer */ 


if (SerialMP=CreatePort (0,0) ) 
if (SerialIO=(struct IOExtSer *) 
CreateExtIO(SerialMP, sizeof (struct IOExtSer)) ) 
SerialIO->io SerFlags=SERF SHARED; /* Turn on SHARED mode */ 
if (OpenDevice (SERIALNAME, OL, (struct IORequest *)SerialIO,0) ) 
printf("%s did not open\n", SERIALNAME) ; 


During the open, the serial device pays attention to a subset of the flags in the io_SerFlags field. 
The flag bits, SERF_SHARED and SERF_7WIRE, must be set before open. For consistency, the 
other flag bits should also be properly set. Full descriptions of all flags will be given later. 


The serial device automatically fills in default settings for all parameters—stop bits, parity, baud 
rate, etc. For the default unit, the settings will come from Preferences. You may need to change 
certain parameters, such as the baud rate, to match your requirements. Once the serial device is 
opened, all characters received will be buffered, even if there is no current request for them. 


Serial Device 267 


READING FROM THE SERIAL DEVICE 


You read from the serial device by passing an IOExtSer to the device with CMD_READ set in 
io_Command, the number of bytes to be read set in ioLength and the address of the read buffer 
set in io_Data. 


#define READ BUFFER SIZE 256 
char SerialReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ 


SerialI0O->10Ser.io Length ie of 
SeriallO->I10Ser.io Data (APTR) &SerialReadBuffer[0]; 
SerialI0O->I10Ser.io Command CMD_READ; 

DoIO((struct IORequest *)SerialI0O) ; 


READ BUFFER_SIZE; 


If you use this example, your task will be put to sleep waiting until the serial device reads 256 bytes 
(or terminates early). Early termination can be caused by error conditions such as a break. The 
number of characters actually received will be recorded in the io_Actual field of the I[OExtSer 
structure you passed to the serial device. 


WRITING TO THE SERIAL DEVICE 


You write to the serial device by passing an IOExtSer to the device with CMD_WRITE set in 
io_Command, the number of bytes to be written set in io_Length and the address of the write 
buffer set in io_Data. 


To write a NULL-terminated string, set the length to -1; the device will output from your buffer 
until it encounters and transmits a value of zero (0x00). 


SerialI0O->10Ser.io Length = -l; 

SerialIO->10Ser.io Data = (APTR)"Life is but a dream. "; 
SerialIO->10Ser.io Command = CMD WRITE; 

DoIO( (struct IORequest *)SerialIO); /* execute write */ 


The length of the request is -1, meaning we are writing a NULL-terminated string. The number of 
characters sent can be found in io_Actual. 


CLOSING THE SERIAL DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). When the last close is 
performed, the device will deallocate all resources and buffers. 


All IORequests must be complete before CloseDevice(). Abort any pending requests with 
AbortIOO. 
if (! (CheckIO(SeriallI0) )) 

{ 

AbortIO((struct IORequest *)SerialI0O); /* Ask device to abort request, if pending */ 

} 


WaitIO((struct IORequest *)SerialIO); /* Wait for abort, then clean up */ 
CloseDevice((struct IORequest *)SerialI0O); 


268 Amiga ROM Kernel Reference Manual: Devices 


A Simple Serial Port Example 


/* 

* Simple Serial.c 

* 

* This is an example of using the serial device. First, we will attempt 
* to create a message port with CreateMsgPort(). Next, we will attempt 
* to create the I0Request with CreateExtIO(). Then, we will attempt to 
* open the serial device with OpenDevice(). If successful, we will write 
* a NULL-terminated string to it and reverse our steps. If we encounter 
* an error at any time, we will gracefully exit. 

* 

* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 

* 

* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

fendif 


void main (void) 


struct MsgPort *SerialMP; /* pointer to our message port */ 
struct IOExtSer *SerialI0O; /* pointer to our I0Request */ 


/* Create the message port */ 
if (SerialMP=CreateMsgPort () ) 


{ 

/* Create the IORequest */ 

if (SerialIO = (struct IOExtSer *) 
CreateExtI0O(SerialMP, sizeof (struct IOExtSer) )) 


/* Open the serial device */ 
if (OpenDevice (SERIALNAME, 0, (struct IORequest *)SerialIO, OL) ) 


/* Inform user that it could not be opened */ 
printf("Error: %s did not open\n", SERIALNAME) ; 
else 


/* device opened, write NULL-terminated string */ 

SerialIO->I0Ser.io Length -1; 

SerialI0O->I10Ser.io Data (APTR) "Amiga "; 

SerialI0->10Ser.io_ Command CMD_WRITE; 

if (DoIO((struct IORequest *)SerialI0O) ) /* execute write */ 
printf ("Write failed. Error - %d\n",SerialIO->10Ser.io Error); 


/* Close the serial device */ 
CloseDevice((struct IORequest *)SerialIO); 


} 
/* Delete the IO0Request */ 
DeleteExtIO(SerialI0O); 
} 
else 
/* Inform user that the IORequest could be created */ 
printf("Error: Could create IORequest\n") ; 


/* Delete the message port */ 
DeleteMsgPort (SerialMP) ; 
} 


else 
/* Inform user that the message port could not be created */ 
printf("Error: Could not create message port\n"); 


Serial Device 269 


DolO() vs. SendlO(). The above example code contains some simplifications. The 
DoIO() function in the example is not always appropriate for executing the CMD_READ 
or CMD_WRITE commands. DoIOQ will not return until the I/O request has finished. 
With serial handshaking enabled, a write request may never finish. Read requests will not 
finish until characters arrive at the serial port. The following sections will demonstrate a 
solution using the SendIO() and AbortIO() functions. 


Alternative Modes for Serial Input or Output 


As an alternative to DoIO(Q) you can use an asynchronous I/O request to transmit the command. 
Asynchronous requests are initiated with SendIO(). Your task can continue to execute while 
the device processes the command. You can occasionally do a CheckIO() to see if the I/O has 
completed. The write request in this example will be processed while the example continues to run: 
SerialIO->10Ser.io_ Length 
SerialIO->I10Ser.io Data (APTR) "Save the whales! "; 


Seriall0->10Ser.io Command CMD WRITE; 
SendIO((struct IORequest *)SerialIO); 


-1; 


iouou 


printf ("CheckIO %1x\n",CheckIO((struct IORequest *)SerialI0O)); 

printf ("The device will process the request in the background\n") ; 
printf ("CheckIO %1x\n",CheckIO((struct IORequest *)SerialIO)); 
WaitIO((struct IORequest *)SerialIO); /* Remove message and cleanup */ 


Most applications will want to wait on multiple signals. A typical application will wait for menu 
messages from Intuition at the same time as replies from the serial device. The following fragment 
demonstrates waiting for one of three signals. The Wait() will wake up if the read request ever 
finishes, or if the user presses Ctrl-C or Ctrl-F from the Shell. This fragment may be inserted into 
the above complete example. 


/* Precalculate a wait mask for the CTRL-C, CTRL-F and message 
* port signals. When one or more signals are received, 

* Wait() will return. Press CTRL-C to exit the example. 

* Press CTRL-F to wake up the example without doing anything. 
* NOTE: A signal may show up without an associated message! 


A 


WaitMask = SIGBREAKF CTRL C| 
SIGBREAKF_CTRL F| 
1L << SerialMP->mp_SigBit; 


SerialIO->10Ser.io Command 
SerialI0->10Ser.io Length 
SerialIO->I0Ser.io Data 
SendIO (SerialI0O) ; 


CMD_READ; 
READ_BUFFER_SIZE; 
(APTR) &SerialReadBuffer [0]; 


printf ("Sleeping until CTRL-C, CTRL-F, or serial input\n"); 


while (1) 
{ 
Temp = Wait (WaitMask); 
printf("Just woke up (YAWN!) \n"); 


if (SIGBREAKF_CTRL_C & Temp) 
break; 


if (CheckIO(SerialIO) ) /* If request is complete... */ 
{ 
WaitIO(SerialI0O); /* clean up and remove reply */ 


printf("%tld bytes received\n",SerialIlO->I10Ser.io Actual); 
break; 


} 


270 Amiga ROM Kernel Reference Manual: Devices 


AbortIO(SerialIO); /* Ask device to abort request, if pending */ 
WaitIO(SerialI0O); /* Wait for abort, then clean up */ 


WaitlO() vs. Remove(). The WaitIOQ function is used above, even if the request 
is already known to be complete. WaitIO(Q on a completed request simply removes the 
reply and cleans up. The Remove() function is not acceptable for clearing the reply port; 
other messages may arrive while the function is executing. 


HIGH SPEED OPERATION 


The more characters that are processed in each I/O request, the higher the total throughput of the 
device. The following technique will minimize device overhead for reads: 


e Use the SDCMD_QUERY command to get the number of characters currently in the buffer 
(see the devices/serial.h Autodocs for information on SDCMD_QUERY). 


e Use DoIOQ( to read all available characters (or the maximum size of your buffer). In this case, 
DoIO(Q is guaranteed to return without waiting. 


e If zero characters are in the buffer, post an asynchronous request (SendIO()) for 1 character. 
When at least one is ready, the device will return it. Now go back to the first step. 


e If the user decides to quit the program, AbortIO() any pending requests. 


USE OF BeginIO() WITH THE SERIAL DEVICE 


Instead of transmitting the read command with either DoIO( or SendIOQ, you might elect to use 
the low level BeginIOQ) interface to a device. 


BeginIOQ works much like SendIO(Q), i.e., asynchronously, except it gives you control over the 
quick I/O bit JOB_QUICK) in the io_Flags field. Quick I/O saves the overhead of a reply message, 
and perhaps the overhead of a task switch. If a quick I/O request is actually completed quickly, 
the entire command will execute in the context of the caller. See the “Exec: Device Input/Output” 
chapter of the Amiga ROM Kernel Reference Manual: Libraries for more detailed information on 
quick I/O. 


The device will determine if a quick I/O request will be handled quickly. Most non-I/O commands 
will execute quickly; read and write commands may or may not finish quickly. 


SerialIO.I0Ser.io Flags |= IOF_QUICK; /* Set QuickIO Flag */ 


BeginIO((struct IORequest *)SerialIO); 
ait: (SerialI0O->10Ser.io Flags & IOF_ QUICK ) 
/* If flag is still set, I/O was synchronous and is now finished. 
* The IORequest was NOT appended a reply port. There is no 
* need to remove or WaitIO() for the message. 
*/ 
printf ("QuickIO\n") ; 
else 
/* The device cleared the QuickIO bit. QuickIO could not happen 
* for some reason; the device processed the command normally. 
* In this case BeginIO() acted exactly like SendIO(). 
*/ 
printf ("Regular I/O\n"); 
WaitIO(SerialI0O); 


Serial Device 271 


The way you réad from the device depends on your need for processing speed. Generally the 
BeginIO() route provides the lowest system overhead when quick I/O is possible. However, if 
quick I/O does not work, the same reply message overhead still exists. 


ENDING A READ OR WRITE USING TERMINATION CHARACTERS 


Reads and writes from the serial device may terminate early if an error occurs or if an end-of-file 
(EOF) is sensed. For example, if a break is detected on the line, any current read request will be 
retumed with the error SerErr_DetectedBreak. The count of characters read to that point will be 
in the io_Actual field of the request. 


You can specify a set of possible end-of-file characters that the serial device is to look for in the 
input stream or output using the SDCDMD_SETPARAMS command. These are contained in an 
io_TermArray that you provide. io_TermArray is used only when the SERF_EOFMODE flag is 
selected (see the “Serial Flags” sectionbelow). 


If EOF mode is selected, each input data character read into or written from the user’s data block 
is compared against those in io_TermArray. If a match is found, the IOExtSer is terminated as 
complete, and the count of characters transferred (including the termination character) is stored in 
io_Actual. 


To keep this search overhead as efficient as possible, the serial device requires that the array of 
characters be in descending order. The array has eight bytes and all must be valid (that is, do not 
pad with zeros unless zero is a valid EOF character). Fill to the end of the array with the lowest 
value termination character. When making an arbitrary choice of EOF character(s), you will get the 
quickest response from the lowest value(s) available. 


/* 
* Terminate Serial.c 

* 

* This is an example of using a termination array for reads from the serial 

* device. A termination array is set up for the characters Q, E, etx (CTRL-D) 

* and eot (CTRL-C). The EOFMODE flag is set in io SerFlags to indicate that 

* we want to use a termination array by sending the SDCMD_SETPARAMS command to 

* the device. Then, a CMD_READ command is sent to the device with 

* io_Length set to 25. 

* 

* The read will terminate whenever one of the four characters in the termination 
* array is received or when 25 characters have been received. 

* 

* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 

* 

* Run from CLI only 

* 


/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 

#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
) 


int chkabort (void) { return(0); } /* really */ 
#fendif 


272 Amiga ROM Kernel Reference Manual: Devices 


void main (void) 
{ 


struct MsgPort *SerialMP; /* Define storage for one pointer */ 
struct IOExtSer *SerialI0; /* Define storage for one pointer */ 


struct I0TArray Terminators = 


{ 

0x51450403, /* QE etx eot */ 

0x03030303 /* fill to end with lowest value */ 
e 


#define READ _BUFFER_SIZE 25 
UBYTE ReadBuff [READ _BUFFER_SIZE]; 
UWORD ctr; 


if (SerialMP=CreatePort (0,0) ) 
{ 
if (SerialIO=(struct IOExtSer *) CreateExtIO(SerialMP, sizeof (struct IOExtSer))) 


{ 

if (OpenDevice (SERIALNAME, OL, (struct IORequest *)SerialIO,0) ) 
printf ("%s did not open\n", SERIALNAME) ; 

else 


/* Tell user what we are doing */ 
printf ("\fLooking for Q, E, EOT or ETX\n"); 


/* Set EOF mode flag 

* Set the termination array 

* Send SDCMD_SETPARAMS to the serial device 
*/ 


SerialIO->io_SerFlags |= SERF_EOFMODE; 
SerialIO->io TermArray = Terminators; 
SerialI0O->I10Ser.io Command = SDCMD SETPARAMS; 
if (DoIO((struct IORequest *)SerialIO) ) 

printf("Set Params failed "); /* Inform user of error */ 
else 

{ 

Seriall0->10Ser.io Length READ BUFFER SIZE; 
SerialI0->10Ser.io Data (APTR) &ReadBuff [0] ; 
SerialI0O->1I10Ser.io Command CMD READ; 
if (DoIO((struct IORequest *)SerialIO)) /* Execute Read */ 

‘ printf("Error: Read failed\n"); 
else 


/* Display all characters received */ 
printf("\nThese characters were read:\n\t\t\tASCII\tHEX\n") ; 
for (ctr=0;ctr<SerialI0->1I10Ser.io Actual;ctrt++) 
printf("\t\t\t %c\t%x\n", ReadBuff [ctr] ,ReadBuff[ctr]); 
printf("\nThe actual number of characters read: %d\n", 
SerialI0->I10Ser.io Actual); 
} 


CloseDevice((struct IORequest *)SerialIO) ; 
} 

DeleteExtIO((struct IORequest *)SerialI0O); 

} 


else 
printf("Error: Could not create IORequest\n") ; 


DeletePort (SerialMP) ; 
} 


else 
printf("Error: Could not create message port\n"); 


The read will terminate before the io_Length number of characters is read if a ‘Q’, ‘E’, ETX, or 
EOT is detected in the serial input stream. 


Serial Device 273 


USING SEPARATE READ AND WRITE TASKS 


In some cases there are advantages to creating a separate [OExtSer for reading and writing. This 
allows simultaneous operation of both reading and writing. Some users of the device have separate 
tasks for read and write operations. The sample code below creates a separate reply port and request 
for writing to the serial device. 


struct IOExtSer *SerialWritelI0O; 
struct MsgPort *SerialWriteMP; 


/* 

* If two tasks will use the same device at the same time, it is preferred 
* use two OpenDevice() calls and SHARED mode. If exclusive access mode 

* is required, then you will need to copy an existing IORequest. 
* 
* 
* 


Remember that two separate tasks will require two message ports. 


/ 
SerialWriteMP = CreatePort (0,0); 
SerialWriteIO = (struct IOExtSer *) 


CreateExtIO( SerialWriteMP, sizeof (struct IOExtSer) ); 


if (SerialWriteMP && SerialWritelIO ) 
{ 


/* Copy over the entire old IO request, then stuff the 
* new Message port pointer. 


wp 


CopyMem( SerialIO, SerialWriteIO, sizeof(struct IOExtSer) ); 
SerialWriteIO->I10Ser.io Message.mn_ReplyPort = SerialWriteMP; 


SerialWriteI0O->I10Ser.io Command 
SerialWriteI0O->10Ser.io Length 
SerialWriteIO->10Ser.io Data 
DoIO(SerialWriteI0O) ; 

} 


CMD_WRITE; 
-1; 
(APTR)"A poet’s food is love and fame"; 


ioe 


Where’s OpenDevice()? This code assumes that the OpenDevice() function has already 
been called. The initialized read request block is copied onto the new write request block. 


274 Amiga ROM Kernel Reference Manual: Devices 


Setting Serial Parameters (SDCMD_SETPARAMS) 


When the serial device is opened, default values for baud rate and other parameters are automatically 
filled in from the serial settings in Preferences. The parameters may be changed by using the 
SDCMD_SETPARAMS command. The flags are defined in the include file devices/serial.h. 


Serial Device Parameters (lIOExtSer) 


IOExtSer 
Field Name Serial Device Parameter It Controls 


io_CtlChar Control characters to use for xON, xOFF, INQ, ACK respectively. Posi- 
tioned within an unsigned longword in the sequence from low address to 
high as listed. INQ and ACK handshaking is not currently supported. 


io_RBufLen Recommended size of the buffer that the serial device should allocate for 
incoming data. For some hardware the buffer size will not be adjustable. 
Changing the value may cause the device to allocate a new buffer, which 
might fail due to lack of memory. In this case the old buffer will continue 
to be used. 


For the built-in unit, the minimum size is 64 bytes. Out-of-range numbers 
will be truncated by the device. When you do an SDCMD_SETPARAMS 
command, the driver senses the difference between its current value and 
the value of buffer size you request. All characters that may already be 
in the old buffer will be discarded. Thus it is wise to make sure that you 
do not attempt buffer size changes (or any change to the serial device, for 
that matter) while any I/O is actually taking place. 


io_ExtFlags An unsigned long that contains the flags SEXTF_MSPON and 
SEXTF_MARK. SEXTF_MSPON enables either mark or space parity. 
SEXTF_MARK selects mark parity (instead of space parity). Unused 
bits are reserved. 


io_Baud The real baud rate you request. This is an unsigned long value in the 
range of 1 to 4,294,967,295. The device will reject your baud request if 
the hardware is unable to support it. 


For the built-in driver, any baud rate in the range of 110 to about 1 
megabaud is acceptable. The built-in driver may round 110 baud requests 
to 112 baud. Although baud rates above 19,200 are supported by the 
hardware, software overhead will limit your ability to “catch” every 
single character that should be received. Output data rate, however, is 
not software-dependent. 


io_BrkTime If you issue a break command, this variable specifies how long, in 
microseconds, the break condition lasts. This value controls the 
break time for all future break commands until modified by another 
SDCMD_SETPARAMS. 


Serial Device 275 


io_TermArray A byte-array of eight termination characters, must be in descending order.. 
If the EOFMODE bit is set in the serial flags, this array specifies eight 
possible choices of character to use as an end of file mark. See the 
section above titled “Ending A Read Using Termination Characters” and 
the SDCMD_SETPARAMS summary page in the Autodocs 


io_ReadLen How many bits per read character, typically a value of 7 or 8. Generally 
must be the same as io_ WriteLen. 


io_WriteLen How many bits per write character; typically a value of 7 or 8. Generally 
must be the same as io_ReadLen. 


io_StopBits How many stop bits are to be expected when reading a character and to be 
produced when writing a character, typically 1 or 2. The built-in driver 
does not allow values above 1 if io_WriteLen is larger than 7. 


io_SerFlags See the “Serial Flags” section below. 


io_Status Contains status information filled in by the SDCMD_QUERY command. 
Break status is cleared by the execution of SDCMD_QUERY. 


You set the serial parameters by passing an IOExtSer to the device with SDCMD_SETPARAMS 
set in io_Command and with the flags and parameters set to the values you want. 


= ~SERF_PARTY_ON; /* set parity off */ 
= SERF XDISABLED; /* set xON/xOFF disabled */ 
SerialI0O->io_ Baud = 9600; * set 9600 baud */ 
SerialIl0->10Ser.io Command = SDCMD SETPARAMS; /* Set params command */ 
if (DoIO((struct IORequest *)SerialI0)) 

printf("Error setting parameters! \n"); 


Seriall0O->io_SerFlags & 
SerialI0->io SerFlags | 


The above fragment modifies two bits in io_SerFlags and changes the baud rate. If the parameters 
you request are unacceptable or out of range, the SDCMD_SETPARAMS command will fail. You 
are responsible for checking the error code and informing the user. 


Proper Time for Parameter Changes. A parameter change should not be performed 
while an I/O request is actually being processed because it might invalidate the request 
handling already in progress. To avoid this, you should use SDCMD_SETPARAMS only 
when you have no serial I/O requests pending. 


SERIAL FLAGS (Bit Definitions For io_SerFlags) 


There are additional serial device parameters which are controlled by flags set in the io_SerFlags 
field of the IOExtSer structure. The default state of all of these flags is zero. SERF_SHARED and 
SERF_7WIRE must always be set before OpenDevice(). The flags are defined in the include file 
devices/serial.h. 


276 Amiga ROM Kernel Reference Manual: Devices 


Flag Name 


SERF_XDISABLED 


SERF_EOFMODE 


SERF_SHARED 


SERF_RAD_BOOGIE 


SERF_QUEUEDBRK 


SERF_7WIRE 


SERF_PARTY_ODD 
SERF_PARTY_ON 


Serial Flags (io_SerFlags) 


Effect on Device Operation 


Disable the XON/XOFF feature. XON/XOFF must be disabled during 
XModem transfers. 


Set this bit if you want the serial device to check input charac- 
ters against io_TermArray and to terminate the read immediately 
if an end-of-file character has been encountered. Note: this bit may 
be set and reset directly in the user’s IOExtSer without a call to 
SDCMD_SETPARAMS. 


Set this bit if you want to allow other tasks to simultaneously access 
the serial port. The default is exclusive-access. Any number of tasks 
may have shared access. Only one task may have exclusive access. If 
someone already has the port for exclusive access, your OpenDevice() 
call will fail. This flag must be set before OpenDevice(). 


If set, this bit activates high-speed mode. Certain peripheral devices 
(MIDI, for example) require high serial throughput. Setting this bit 
high causes the serial device to skip certain of its internal checking 
code to speed throughput. Use SERF_RAD_BOOGIE only when you 
have: 


e Disabled parity checking 

e Disabled XON/XOFF handling 

e Use 8-bit character length 

e Do not wish a test for a break signal 


Note that the Amiga is a multitasking system and has immediate 
processing of software interrupts. If there are other tasks running, 
it is possible that the serial driver may be unable to keep up with 
high data transfer rates, even with this bit set. 


If set, every break command that you transmit will be enqueued. 
This means that all commands will be executed on a FIFO (first 
in, first out) basis. 


If this bit is cleared (the default), a break command takes immediate 
precedence over any serial output already enqueued. When the 
break command has finished, the interrupted request will continue 
(if not aborted by the user). 


If set at OpenDevice() time, the serial device will use seven-wire 
handshaking for RS-232-C communications. Default is three-wire 
(pins 2, 3, and 7). 

If set, selects odd parity. If clear, selects even parity. 


If set, parity usage and checking is enabled. Also see the 
SERF_MSPON bit described under io_ExtFlags above. 


Serial Device 277 


Querying The Serial Device 


You query the serial device by passing an IOExtSer to the device with SDCMD_QUERY set in 
io_Command. The serial device will respond with the status of the serial port lines and registers, 
and the number of unread characters in the read buffer. 


UWORD Serial Status; 
ULONG Unread Chars; 


SerialIlO->1I10Ser.io_ Command = SDCMD_ QUERY; /* indicate query */ 
SendIO((struct IORequest *)SerialIO); 


Serial Status = SerialIO-D>io_ Status; /* store returned status */ 
Unread Chars = SerialIO->10Ser.io Actual; /* store unread count */ 


The 16 status bits of the serial device are returned in io_Status; the number of unread characters is 
returned in io_Actual. 


Serial Device Status Bits 


Active Symbol Function 


— Reserved 
— Reserved 
high = (RI) Parallel Select on the A1000. On the A500 
and A2000, Select is also connected to the se- 
rial port’s Ring Indicator. (Be cautious when 
making cables.) 
(DSR) Data set ready 
(CTS) Clear to send 
(CD) Carrier detect 
(RTS) Ready to send 
(DTR) Data terminal ready 
Read overrun 
Break sent 
Break received 
Transmit x-OFFed 
Receive x-OFFed 
(reserved) 





278 Amiga ROM Kernel Reference Manual: Devices 


Sending the Break Command 


You send a break through the serial device by passing an IOExtSer to the device with 
SDCMD_BREAK set in io_Command. The break may be immediate or queued. The choice 
is determined by the state of flag SERF_QUEUEDBRK in io_SerFlags. 


SerialIO->10Ser.io Command = SDCMD BREAK; /* send break */ 
SendIO((struct IORequest *)SerialIO); 


The duration of the break (in microseconds) can be set in io_BrkTime. The default is 250,000 
microseconds (.25 seconds). 


Error Codes from the Serial Device 


The serial device returns error codes whenever an operation is attempted. 


SerialIO->10Ser.io Command = SDCMD_SETPARAMS; /* Set parameters */ 
if (DoIO((struct IORequest *)SerialI0O) ) 
printf("Set Params failed. Error: %d ",SerialIO->I0Ser.io Error); 


The error is returned in the io_Error field of the IOExtSer structure. 


Serial Device Error Codes 


Error Explanation 


SerErr_DevBusy Device in use 
SerErr_BaudMismatch Baud rate not supported by hardware 
SerErr_BufErr Failed to allocate new read buffer 
SerErr_InvParam Bad parameter 

SerErr_LineErr Hardware data overrun 


SerErr_ParityErr Parity error 

SerErr_TimerErr Timeout (if using 7-wire handshaking) 
SerErm_BufOverflow Read buffer overflowed 
SerErr_NoDSR No Data Set Ready 
SerErr_DetectedBreak Break detected 

SerErr_UnitBusy Selected unit already in use 





Serial Device 279 


Multiple Serial Port Support 


Applications that use the serial port should provide the user with a means to select the name and 
unit number of the driver. The defaults will be “‘serial.device” and unit number 0. Typically unit 
0 refers to the user-selected default. Unit 1 refers to the built-in serial port. Numbers above 1 are 
for extended units. The physically lowest connector on a board will always have the lowest unit 
number. 


Careful attention to error handling is required to survive in a multiple port environment. Differ- 
ing serial hardware will have different capabilities. The device will refuse to open non-existent 
unit numbers (symbolic name mapping of unit numbers is not provided at the device level). The 
SDCMD_SETPARAMS command will fail if the underlying hardware cannot support your param- 
eters. Some devices may use quick I/O for read or write requests, others will not. Watch out for 
partially completed read requests; io_Actual may not match your requested read length. 


If the Tool Types mechanism is used for selecting the device and unit, the defaults of “DE- 
VICE=serial.device” and “UNIT=0” should be provided. The user should be able to permanently 
set the device and unit in a configuration file. 


Taking Over the Hardware 


For some applications use of the device driver interface is not possible. By following the established 
rules, applications may take over the serial interface at the hardware level. This extreme step is not, 
however, encouraged. Taking over means losing the ability to work with additional serial ports, and 
will limit future compatibility. 


Access to the hardware registers is controlled by the misc.resource. See the “Resources” chapter, 
and exec/misc.i for details. The MR_SERIALBITS and MR_SERIALPORT units control the serial 
registers. 


One additional complication exists. The current serial device will not release the misc.resource bits 
until after an expunge. This code provides a work around: 


/* 
* A safe way to expunge ONLY a certain device. 

* This code attempts to flush ONLY the named device out of memory and 
* nothing else. If it fails, no status is returned (the information 
yo have no valid use after the Permit(). 

* 

#include <exec/types.h> 

#include <exec/execbase.h> 


void FlushDevice (char *); 
extern struct ExecBase *SysBase; 


void FlushDevice (name) 
char *name; 


struct Device *devpoint; 


Forbid (); /* ugly */ 


if (devpoint = (struct Device *)FindName (&SysBase->DeviceList,name) ) 
RemDevice (devpoint) ; 
Permit (); 


280 Amiga ROM Kernel Reference Manual: Devices 


Advanced Example of Serial Device Usage 


‘* Complex Serial.c 

: Complex tricky example of serial.device usage 

7 Compile with SAS C 5.10 le -bl -cfistq -v -y -L 
: Run from CLI only 


/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <exec/io.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


void main (void) 


struct MsgPort *SerialMP; /* Define storage for one pointer */ 
struct IOExtSer *SerialIO; /* Define storage for one pointer */ 


#define READ BUFFER SIZE 32 
char SerialReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ 


struct IOExtSer *SerialWriteIO = 0; 
struct MsgPort *SerialWriteMP = 0; 
ULONG Temp; 

ULONG WaitMask; 


if (SerialMP=CreatePort (0,0) ) 


{ 
if (SerialIO=(struct IOExtSer *) 
CreateExtIO(SerialMP, sizeof (struct IOExtSer)) ) 


{ 
Seriall0->io_ SerFlags=0; /* Example of setting flags */ 


if (OpenDevice (SERIALNAME, 0L,SerialIO,0) ) 
printf ("%s did not open\n", SERIALNAME) ; 
else 
{ 
SerialIO->1I0Ser.io_Command 
SerialIO->io_SerFlags 
SerialIO->io_ SerFlags 
SerialIO->io_ Baud 
if (Temp=DoI0O(SerialI0) ) 
printf("Error setting parameters - code %ld!\n",Temp); 


SDCMD_SETPARAMS; 
~SERF PARTY ON; 
SERF_XDISABLED; 
96003 


—m 


SerialI0O->I0Ser.io_ Command 
SerialIO->I0Ser.io Length 
SerialIO->10Ser.io Data 
SendIO(SerialIO); 

printf ("CheckIO %1x\n",CheckIO(SerialI0O)); 

printf ("The device will process the request in the background\n"); 
printf ("CheckIO %1x\n",CheckIO(SerialIO) ); 

WaitIO(SerialI0O); 


CMD_WRITE; 
-1; 
(APTR) "Amiga."; 


SerialIO->10Ser.io_Command CMD_WRITE; 


SerialIO->10Ser.io Length = -l1; 
SerialIO->10Ser.io Data = (APTR)"Save the whales! "; 
DoIO(SerialI0O); /* execute write */ 


Serial Device 281 


SerialI0O->10Ser.io Command 
SerialIlO->10Ser.io Length 
SerialIO->I10Ser.io Data 
DoIO(SeriallIO); 


CMD_WRITE; 

-1; 

(APTR) "Life is but a dream."; 
execute write */ 


~ 
* 


SerialIO->10Ser.io Command CMD WRITE; 

SerialIO->10Ser.io Length -1;—— 

SerialIO->10Ser.io Data = (APTR)"Row, row, row your boat."; 
SeriallO->I0Ser.io Flags = IOF QUICK; 

BeginIO(SerialI0O); — = 


if (SerialIO->I0Ser.io Flags & IOF QUICK ) 
{ 


/* 
* Quick IO could not happen for some reason; the device processed 
* the command normally. In this case BeginIO() acted exactly 
* like SendIO(). 

x/ 


printf ("Quick IO\n"); 
} 
else 


{ 


/* If flag is still set, IO was synchronous and is now finished. 
* The IO request was NOT appended a reply port. There is no 
* need to remove or WaitIO() for the message. 


ef 


printf ("Regular IO\n"); 
} 


WaitIO(SeriallI0O); 


SerialIO->10Ser.io_ Command 
SerialIO->10Ser.io Length -1; 

SerialIO->I0Ser.io Data (APTR) "Row, row, row your boat."; 
SerialI0O->10Ser.io Flags = IOF_ QUICK; 

BeginI0O(SeriallI0O) ; 


CMD_UPDATE; 


iouew 


if (0 == SerialIO->10Ser.io Flags & IOF_QUICK ) 
{ 


/* 

* Quick IO could not happen for some reason; the device processed 
* the command normally. In this case BeginIO() acted exactly 

* like SendIO(). 

*/ 


printf ("Regular IO\n"); 
Wait1I0O(SerialI0); 
} 


else 


/* If flag is still set, IO was synchronous and is now finished. 
* The IO request was NOT appended a reply port. There is no 

* need to remove or WaitIO() for the message. 

*/ 


printf ("Quick IO\n"); 
} 


/* Precalculate a wait mask for the CTRL-C, CTRL-F and message 
* port signals. When one or more signals are received, 

* Wait() will return. Press CTRL-C to exit the example. 

* Press CTRL-F to wake up the example without doing anything. 
* NOTE: A signal may show up without an associated message! 


WaitMask = SIGBREAKF CTRL C| 
SIGBREAKF_ CTRL F| 
1L << SerialMP->mp_SigBit; 


282 Amiga ROM Kernel Reference Manual: Devices 


SerialIO->10Ser.io_Command 
SerialIO->I0Ser.io Length 
SerialIO->10Ser.io Data 
SendIO(SerialIO); 


CMD_READ; 
READ_BUFFER_SIZE; 
(APTR) &SerialReadBuffer [0]; 


printf ("Sleeping until CTRL-C, CTRL-F, or serial input\n"); 
while (1) 
{ 


Temp = Wait (WaitMask) ; 
printf ("Just woke up (YAWN!) \n"); 


if (SIGBREAKF_CTRL_C & Temp) 
break; 


if (CheckIO(SerialIO) ) /* If request is complete... */ 
{ 
WaitIO(SerialI0O); /* clean up and remove reply */ 


printf("%tld bytes received\n",SerialIO->I0Ser.io Actual); 
break; 
} 

} 


AbortIO(SerialIO); /* Ask device to abort request, if pending */ 
WaitIO(SerialI0O); /* Wait for abort, then clean up */ 


If two tasks will use the same device at the same time, it is preferred 
use two OpenDevice() calls and SHARED mode. If exclusive access mode 
is required, then you will need to copy an existing IO request. 


Oe OE 


Remember that two separate tasks will require two message ports. 


/ 


SerialWriteMP 
SerialWriteIO 


CreatePort (0,0); 
(struct IOExtSer *) 
CreateExtIO( SerialWriteMP, sizeof (struct IOExtSer) ); 


if (SerialWriteMP && SerialWriteIO ) 
{ 


/* Copy over the entire old IO request, then stuff the 
* new Message port pointer. 
*/ 


CopyMem( SerialIO, SerialWriteIO, sizeof(struct IOExtSer) ); 
SerialWriteIO->10Ser.io Message.mn_ReplyPort = SerialWriteMP; 


SerialWriteI0->I0Ser.io Command 
SerialWriteIO->I10Ser.io Length 
SerialWriteI0O->I10Ser.io Data 
DolIO (SerialWriteI0) ; 

} 


if (SerialWriteMP) 
DeletePort (SerialWriteMP) ; 


CMD WRITE; 
-1; 
(APTR)"A poet’s food is love and fame"; 


if (SerialWriteIO) 
DeleteExtIO(SerialWritelI0O) ; 


CloseDevice (SerialI0O); 


DeleteExtIO(SerialI0O) ; 
} 


else 
printf ("Unable to create IORequest\n"); 


DeletePort (SerialMP); 
} 


else 
printf ("Unable to create message port\n"); 
} 


Serial Device 283 


Additional Information on the Serial Device 


Additional programming information on the serial device can be found in the include files and the 
Autodocs for the serial device. Both are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Serial Device Information 


INCLUDES devices/serial.h 


devices/serial.i 
AUTODOCS serial.doc 





284 Amiga ROM Kernel Reference Manual: Devices 


chapter thirteen 
TIMER DEVICE 


The Amiga timer device provides a general interface to the Amiga’s internal clocks. Through the 
timer device, time intervals can be measured, time delays can be effected, system time can be set 
and retrieved, and arithmetic operations can be performed on time values. 













New Timer Features for Version 2.0 
Feature Description 


UNIT_ECLOCK New timer device unit 
UNIT_WAITUNTIL New timer device unit 
UNIT_WAITECLOCK New timer device unit 


ReadEClock() New function 





Compatibility Warning: The new features for 2.0 are not backwards compatible. 


Timer Device 285 


Timer Device Commands and Functions 


Command Operation 


TR_ADDREQUEST Request that the timer device wait a specified period of time before 


replying to the request. 

TR_GETSYSTIME Get system time and place in a timeval structure. 

TR_SETSYSTIME Set the system time from the value in a timeval structure. 

Device Functions 

AddTime() Add one timeval structure to another. The result is placed in the first 
timeval structure. 

CmpTime() Compare one timeval structure to another. The result is retuned as a 
longword. 

GetSysTimeQ) Get system time and place in a timeval structure. 

ReadEClock() Read the current 64 bit value of the E-Clock into an EClockVal 
structure. The count rate of the E-Clock is also returned. (V36) 

SubTime(Q) Subtract one timerequest structure from another. The result is placed 


in the first timerequest structure. 


Exec Functions as Used in This Chapter 


AbortIO() Abort a command to the timer device. 

CheckIO(Q) Retum the status of an I/O request. 

CloseDevice() Relinquish use of the timer device. All requests must be complete 
before closing. 

DoIOQ Initiate a command and wait for completion (synchronous request). 

OpenDevice() Obtain use of the timer device. The timer device may be opened 
multiple times. 

SendIO() Initiate a command and retum immediately (asynchronous request). 


Exec Support Functions as Used In This Chapter 


CreateExtIO() Create an extended I/O request structure of type timerequest. This 
structure will be used to communicate commands to the timer device. 

CreatePort() Create a signal message port for reply messages from the timer device. 
Exec will signal a task when a message arrives at the reply port. 

DeleteExtIO() Delete the timerequest extended I/O request structure created by 
CreateExtIO(Q. 

DeletePort() Delete the message port created by CreatePort(). 


286 Amiga ROM Kernel Reference Manual: Devices 


Device Interface 


The timer device operates in a similar manner to the other Amiga devices. To use it, you must first 
open it, then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga 
System Devices” chapter for general information on device usage. 


The timer device also provides timer functions in addition to the usual I/O request protocol. These 
functions still require the device to be opened with the proper timer device unit, but do not require 
a message port. However, the base address of the timer library must be obtained in order to use the 
timer functions. 


The two modes of timer device operation are not mutually exclusive. You may use them both within 
the same application. 


The I/O request used by the timer device is called timerequest. 


struct timerequest 

{ 
struct IORequest tr node; 
struct timeval tr_time; 


° 
, 


The timer device functions are passed a time structure, either timeval for non E-Clock units or 
EClockVal for E-Clock units. 


struct timeval 


ULONG tv_secs; /* seconds */ 
ULONG tv_micro; /* microseconds */ 
} 


struct EClockVal 
{ 


ULONG ev_hi; /* Upper longword of E-Clock time */ 
ULONG ev_lo; /* Lower longword of E-Clock time */ 
}e 


See the include file devices/timer.h for the complete structure definitions. Time requests fall into 
three categories: 


e Time delay - wait a specified period of time. A time delay causes an application to wait a certain 
length of time. When a time delay is requested, the number of seconds and microseconds to 
delay are specified in the I/O request. 


e Time measure - how long something takes to complete. A time measure is a three-step 
procedure where the system or E-Clock time is retrieved, an operation or series of operations 
is performed, and then another time retrieval is done. The difference between the two time 
values is the measure of the duration of the operation. 


e 


Time alarm - wait till a specific time. A time alarm is a request to be notified when a specific 
time value has occurred. It is similar to a time delay except that the absolute time value is 
specified in the I/O request. 


What is an E-Clock? The E-Clock is the clock used by the Motorola 68000 processor 
family to communicate with other Motorola 8-bit chips. The E-Clock returns two distinct 
values—the E-Clock value in the form of two longwords and the count rate (tics/second) 
of the E-Clock. The count rate is related to the master frequency of the machine and is 
different between PAL and NTSC machines. 


Timer Device 287 


TIMER DEVICE UNITS 


There are five units in the timer device. 






Timer Device Units 
a 






















UNIT_MICROHZ Interval Timing 
UNIT_VBLANK Interval Timing 
UNIT_ECLOCK Interval Timing 
UNIT_WAITUNTIL Time Event Occurrence 


UNIT_WAITECLOCK Time Event Occurrence 


The VBLANK timer unit is very stable and has a granularity comparable to the vertical blanking 
time. When you make a timing request, such as “signal me in 21 seconds,” the reply will come 
at the next vertical blank after 21 seconds have elapsed. This timer has very low overhead and 
may be more accurate then the MICROHZ and ECLOCK units for long time periods. Keep in 
mind that the vertical blanking time varies depending on the display mode. 


The MICROHZ timer unit uses the built-in precision hardware timers to create the timing 
interval you request. It accepts the same type of command—“signal me in so many seconds 
and microseconds.” The microhertz timer has the advantage of greater resolution than the 
vertical blank timer, but it may have less accuracy over long periods of time. The microhertz 
timer also has much more system overhead, which means accuracy is reduced as the system 
load increases. It is primarily useful for short-burst timing for which critical accuracy is not 
required. 


The ECLOCK timer unit uses the Amiga E-Clock to measure the time interval you request. 
This is the most precise time measure available through the timer device. 


The WAITUNTIL timer unit acts as an alarm clock for time requests. It will signal the task 
when systime is greater than or equal to a specified time value. It has the same granularity as 
the VBLANK timer unit. 


The WAITECLOCK timer unit acts as an alarm clock for time requests. It will signal the task 
when the E-Clock value is greater than or equal to a specified time value. It has the same 
granularity as the ECLOCK timer unit. 


Granularity vs. Accuracy. Granularity is the sampling frequency used to check the 
timers. Accuracy is the precision of a measured time interval with respect to the same 
time interval in real-time. We speak only of granularity because the sampling frequency 
directly affects how accurate the timers appear to be. 


288 Amiga ROM Kernel Reference Manual: Devices 


OPENING THE TIMER DEVICE 


Three primary steps are required to open the timer device: 


e Create a message port using CreatePort(). Reply messages from the device must be directed 
to a message port. 


e Create an I/O request structure of type timerequest using CreateExtIO(). 


e Open the timer device with one of the five timer device units. Call OpenDevice() passing a 
pointer to the timerequest. 


struct MsgPort *TimerMP; /* Message port pointer */ 
struct timerequest *TimerIO; /* I/O structure pointer */ 


/* Create port for timer device communications */ 
if (!(TimerMP = CreatePort (0,0))) 
cleanexit(" Error: Can’t create port\n",RETURN_ FAIL); 


/* Create message block for device IO */ 
if (!(TimerIO = (struct timerequest *) 
CreateExtIO(TimerMP) (sizeof timerequest)) ) 
cleanexit (" Error: Can’t create IO request\n",RETURN_ FAIL); 


/* Open the timer device with UNIT MICROHZ */ 


if (error=OpenDevice (TIMERNAME, UNIT MICROHZ, TimerIO, 0)) 
cleanexit (" Error: Can’t open Timer.device\n",RETURN_FAIL); 


The procedure for applications which only use the timer device functions is slightly different: 
e Declare the timer device base address variable TimerBase in the global data area. 
e Allocate memory for a timerequest structure and a timeval structure using AllocMem(). 
e Call OpenDevice(), passing the allocated timerequest structure. 


e Set the timer device base address variable to point to the timer device base. 


struct Library *TimerBase; /* global library pointer */ 


struct timerequest *TimerI0O; 
struct timeval *timel; 


/* Allocate memory for timerequest and timeval structures */ 
TimerIO=(struct timerequest *)AllocMem(sizeof (struct timerequest), 
MEMF PUBLIC | MEMF_CLEAR) ; 
timel=(struct timeval *)AllocMem(sizeof (struct timeval), 
MEMF_PUBLIC | MEMF_CLEAR) ; 
if (!TimerIO | !timel) 
cleanexit (" Error: Can’t allocate memory for I/O structures\n", RETURN FAIL); 


if (error=OpenDevice (TIMERNAME, UNIT MICROHZ, TimerI0O, 0) ) 
cleanexit(" Error: Can’t open Timer.device\n", RETURN_FAIL); 


/* Set up pointer for timer functions */ 
TimerBase = (struct Library *)TimerIO->tr_node.io Device; 


Timer Device 289 


CLOSING THE TIMER DEVICE 


Each OpenDevice() must eventually be matched by a call to CloseDevice(). 


All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort 
them with AbortIO(Q. 


if (! (CheckIO(TimerI0) )) 
AbortIO(TimerI0O); /* Ask device to abort any pending requests */ 


} 
WaitIO(TimerIO); /* Clean up */ 
CloseDevice((struct IORequest *)TimerIO); /* Close Timer device */ 


System Time 


The Amiga has a system time feature provided for the convenience of the developer. It is a 
monotonically increasing time base which should be the same as real time. The timer device 
provides two commands to use with the system time. In addition, there are utility functions in 
utility.library which are very useful with system time. See the “Utilities Library” chapter of the 
Amiga ROM Kernel Reference Manual: Libraries for more information. 


The command TR_SETSYSTIME sets the system’s idea of what time it is. The system starts out 
at time ‘“‘zero” so it is safe to set it forward to the “real” time. However, care should be taken when 
setting the time backwards. 


The command TR_GETSYSTIME is used to get the system time. The timer device does not 
interpret system time to any physical value. By convention, it tells how many seconds have passed 
since midnight, January 1, 1978. Your program must calculate the time from this value. 


The function GetSysTime() can also be used to get the system time. It returns the same value as 
TR_GETSYSTIME, but uses less overhead. 


Whenever someone asks what time it is using TR-GETSYSTIME, the return value of the system 
time is guaranteed to be unique and unrepeating so that it can be used by applications as a unique 
identifier. 


System time at boot time. The timer device sets system time to zero at boot time. 
AmigaDOS will then reset the system time to the value specified on the boot disk. If the 
AmigaDOS C:SetClock command is given, this also resets system time. 


Here is a program that can be used to determine the system time. The command is executed by the 
timer device and, on retum, the caller can find the data in his request block. 


~~ 


Get_Systime.c 
Get system time example 
Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 


* 
* 
* 
* 
* 
* 
* Run from CLI only 

*/ 

#include <exec/types.h> 
#include <exec/io.h> 
#include <exec/memory.h> 
#include <devices/timer.h> 


290 Amiga ROM Kernel Reference Manual: Devices 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <clib/dos_ protos.h> 


#include <clib/intuition_protos.h> 


#include <stdio.h> 


#ifdef LATTICE 
int CXBRK(void) { return(0); 


} 
int chkabort (void) { return(0); 


#endif 


struct timerequest *TimerI0O; 
struct MsgPort *TimerMP; 
struct Message *TimerMSG; 


VOID main(VOID); 

void main() 

{ 

LONG error; 

ULONG days,hrs, secs,mins,mics; 


if (TimerMP = CreatePort (0,0) ) 


/* Disable SAS CTRL/C handling */ 
} /* really */ 


if (TimerIO = (struct timerequest *) 
CreateExtI0O(TimerMP, sizeof (struct timerequest)) ) 


/* Open with UNIT_VBLANK, but any unit can be used */ 
if (! (error=OpenDevice (TIMERNAME, UNIT _VBLANK, (struct IORequest *)TimerIO,0L))) 
{ 


/* Issue the command and wait for it to finish, then get the reply */ 
TimerIO->tr_node.io Command = TR_GETSYSTIME; 
DoIO((struct IORequest *) TimerIO); 


/* Get the results and close the timer device */ 
mics=TimerIO->tr_time.tv_micro; 
secs=TimerI0->tr_time.tv_secs; 


/* Compute days, hours, etc. */ 


mins=secs/60; 
hrs=mins/60; 
days=hrs/24; 
secs=secs%60; 
mins=mins%60; 
hrs=hrs%24; 


/* Display the time */ 

printf ("\nSystem Time (measured from Jan.1,1978) \n"); 

printf(" Days Hours Minutes Seconds Microseconds\n") ; 
printf("%6ld %6ld %6ld %6ld %101d\n",days,hrs,mins, secs,mics) ; 


/* Close the timer device */ 
CloseDevice ((struct IORequest *) TimerIO); 


} 


else 


printf ("\nError: Could not open timer device\n"); 


/* Delete the IORequest structure */ 


DeleteExtIO(TimerIO); 
} 


else 


printf("\nError: Could not create I/O structure\n"); 


/* Delete the port */ 
DeletePort (TimerMP) ; 
} 


else 


printf ("\nError: Could not create port\n"); 


Timer Device 291 


Adding a Time Request 


Time delays and time alarms are done by opening the timer device with the proper unit and submitting 
a timerequest to the device with TR-ADDREQUEST set in io_Command and the appropriate 
values set in tv_secs and tv_micro. 


Time delays are used with the UNIT_MICROHZ, UNIT_VBLANK, and UNIT_ECLOCK units. 
The time specified in a time delay timerequest is a relative measure from the time the request 
is posted. This means that the tv_secs and tv_micro fields should be set to the amount of delay 
required. 


When the specified amount of time has elapsed, the driver will send the timerequest back via 
ReplyMsg(). You must fill in the ReplyPort pointer of the timerequest structure if you wish to be 
signaled. Also, the number of microseconds must be normalized; it should be a value less than one 
million. 


For a minute and a half delay, set 60 in tv_secs and 500,000 in tv_micro. 


TimerIO->tr_node.io Command = TR_ADDREQUEST; 
TimerIO->tr_time.tv_secs = 60; /* Delay a minute */ 
TimerIO->tr_time.tv_micro = 500000; /* and a half mS, 
DoIO(TimerI0) ; - 


Time alarms are used with the UNIT_WAITUNTIL and UNIT_WAITECLOCK units. The tv_secs 
and tv_micro fields should be set to the absolute time value of the alarm. For an alarm at 10:30 
tonight, the number of seconds from midnight, January 1, 1978 till 10:30 tonight should be set in 
tv_secs. The timer device will not retum until the time is greater than or equal to the absolute time 
value. 


For our purposes, we will set an alarm for three hours from now by getting the current system time 
and adding three hours of seconds to it. 


#define SECSPERHOUR (60*60) 
struct timeval *systime; 


GetSysTime (systime) ; /* Get current system time */ 


TimerIO->tr_node.io Command = TR_ADDREQUEST; 

TimerIO->tr_time.tv_secs = systime.tv_secs+ (SECSPERHOUR*3) ; /* Alarm in 3 hours */ 
TimerIO->tr_time.tv_micro = systime.tv_micro; 

DolO(TimerIO) ; ~ 


Time requests with the E-Clock Units. Time requests with the E-Clock units— 
UNIT_ECLOCK and UNIT_WAITECLOCK—work the same as the other units except 
that the values specified in their I/O requests are compared against the value of the E-Clock. 
See the section “E-Clock Time and Its Relationship to Actual Time” below. 


Remember, you must never reuse a timerequest until the timer device has replied to it. When you 
submit a timer request, the driver destroys the values you have provided in the timeval structure. 
This means that you must reinitialize the time specification before reposting a timerequest. 


292 Amiga ROM Kernel Reference Manual: Devices 


Keep in mind that the timer device provides a general time-delay capability. It can signal you 
when at least a certain amount of time has passed. The timer device is very accurate under normal 
system loads, but because the Amiga is a multitasking system, the timer device cannot guarantee 
that exactly the specified amount of time has elapsed—processing overhead increases as more tasks 
are run. High-performance applications (such as MIDI time-stamping) may want to take over the 
16-bit counters of the CIA B timer resource instead of using the timer device. 


Problems with small time requests in V1.3 and earlier versions. You must also take 
care to avoid posting a timerequest of less than 2 microseconds with the UNIT_MICROHZ 
timer device if you are using V1.3 or earlier versions of the system software. In V1.3 
and earlier versions of the Amiga system software, sending a timerequest for 0 or 1 
microseconds can cause a system crash. Make sure all your timer requests are for 2 
microseconds or more when you use the UNIT_MICROHZ timer with those versions. 


MULTIPLE TIMER REQUESTS 


Multiple requests may be posted to the timer driver. For example, you can make three timer requests 
in a row: 


Signal me in 20 seconds (request 1) 
Signal me in 30 seconds (request 2) 
Signal me in 10 seconds (request 3) 


As the timer queues these requests, it changes the time values and sorts the timer requests to service 
each request at the desired interval, resulting effectively in the following order: 


(request 3) in now+10 seconds 
(request 1) 10 seconds after request 3 is satisfied 
(request 2) 10 seconds after request 1 is satisfied 


If you wish to send out multiple timer requests, you have to create multiple request blocks. You can 
do this by allocating memory for each timerequest you need and filling in the appropriate fields 
with command data. Some fields are initialized by the call to the OpenDevice() function. So, for 
convenience, you may allocate memory for the timerequests you need, call OpenDevice() with 
one of them, and then copy the initialized fields into all the other timerequests. 


It is also permissible to open the timer device multiple times. In some cases this may be easier than 
opening it once and using multiple requests. When multiple requests are given, SendIO() should 
be used to transmit each one to the timer. 


ae 


+ 4% 0 OF OF OF OO OO 


Multiple Timers.c 


This program is designed to do multiple (3) time requests using one 
OpenDevice. It creates a message port - TimerMP, creates an 

extended I/O structure of type timerequest named TimerIO[0] and 

then uses that to open the device. The other two time request 
structures - TimerIO[1] and TimerIO[2] - are created using AllocMem 

and then copying TimerIO[0] into them. The tv secs field of each 
structure is set and then three SendIOs are done with the requests. 

The program then goes into a while loop until all messages are received. 


Compile with SAS C 5.10 le -bl -cfistq -v -y -L 


Run from CLI only 
/ 


Timer Device 293 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <devices/timer.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


VOID main (VOID) ; 


void main (void) 

{ 

struct timerequest *TimerIO[3]; 
struct MsgPort *TimerMP; 

struct Message *TimerMSG; 


ULONG error,x, seconds[3]={4,1,2}, microseconds[3]={0,0,0}; 


int allin = 3; 
char *position[]={"last","second","first"}; 


if (TimerMP = CreatePort (0,0)) 
{ 


if (TimerIO[0] = (struct timerequest *) 
CreateExtIO(TimerMP, sizeof (struct timerequest)) ) 


/* Open the device once */ 


if (! (error=OpenDevice( TIMERNAME, UNIT VBLANK, (struct IORequest *) TimerIO[0], OL))) 
{ 


/* Set command to TR_ADDREQUEST */ 
TimerI0(0}->tr_node.io Command = TR_ADDREQUEST; 


if (TimerIO[1]=(struct timerequest *) 


AllocMem(sizeof (struct timerequest),MEMF PUBLIC | MEMF_CLEAR) ) 


{ 


if (TimerIO[2]=(struct timerequest *) 


AllocMem(sizeof (struct timerequest),MEMF PUBLIC | MEMF_CLEAR) ) 


/* Copy fields from the request used to open the timer device */ 


*TimerIO[1] = *TimerIO[0]; 
*TimerIO[(2] = *TimerIO(0]; 


/* Initialize other fields */ 
for (x=0;x<3;x++) 


TimerIO[x]->tr_time.tv_secs = seconds[x]; 
TimerIO(x]->tr_time.tv_micro = microseconds[x]; 
printf ("\nInitializing TimerIO[%d]",x); 

} 


printf ("\n\nSending multiple requests\n\n") ; 


/* Send multiple requests asynchronously */ 
/* Do not got to sleep yet... */ 
SendIO((struct IORequest *)TimerIO[0)); 
SendIO((struct IORequest *)TimerIO[1]); 
SendIO((struct IORequest *)TimerIO[2]); 


/* There might be other processing done here */ 


/* Now go to sleep with WaitPort() waiting for the requests */ 


while (allin) 
{ 


WaitPort (TimerMP) ; 
/* Get the reply message */ 
TimerMSG=GetMsg (TimerMP) ; 
for (x=0;x<3;x++) 
if (TimerMSG==(struct Message *)TimerIO[x]) 


printf ("Request %ld finished %s\n",x, position[--allin]); 


294 Amiga ROM Kernel Reference Manual: Devices 


FreeMem(TimerI0[2],sizeof (struct timerequest) ); 


else 
printf("Error: could not allocate TimerIO[2] memory\n") ; 


FreeMem(TimerI0[1],sizeof (struct timerequest) ); 
else 
printf("Error could not allocate TimerIO[1] memory\n"); 


CloseDevice((struct IORequest *) TimerIO[0]); 
} 


else 
printf("\nError: Could not OpenDevice\n") ; 


DeleteExtIO((struct IORequest *) TimerIO[0]); 
} 


else 
printf("Error: could not create IORequest\n"); 


DeletePort (TimerMP) ; 
} 


else 
printf("\nError: Could not CreatePort\n") ; 


If all goes according to plan, TimerIO[1)] will finish first, TimerI0[2] will finish next, and 
TimerI0O[0] will finish last. 


Using the Time Arithmetic Functions 


As indicated above, the time arithmetic functions are accessed in the timer device structure as if 
they were a routine library. To use them, you create an IORequest block and open the timer. In the 
1ORequest block is a pointer to the device’s base address. This address is needed to access each 
routine as an offset—for example, LVOAddTime, _LVOSubTime, _LYVOCmpTime—from that 
base address. 


" Timer _Arithmetic.c 

: Example of timer device arithmetic functions 

yh Compile with SAS C 5.10 le -bl -cfistq -v -y -L 
* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/io.h> 
#include <exec/memory.h> 
#finclude <devices/timer.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/timer_protos.h> 
#include <stdio.h> 

#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 


Timer Device 295 


#tendif 
struct Library *TimerBase; /* setup the interface variable (must be global) */ 


void main(int argc,char **argv) 


struct timeval *timel, *time2, *time3; 
struct timerequest *tr; 

LONG error, result; 

/* ew ewe www www ewww ww ewww we ne ewe wow owe x/ 
/* Get some memory for our structures =o 
Jeeseccoecesi cect cccecctoese ses saecS 


timel=(struct timeval Piaiccslen (aeons abner timeval), 
MEMF_ PUBLIC | MEMF_CLEAR) ; 
time2=(struct timeval *)AllocMem(sizeof (struct timeval), 
MEMF_PUBLIC | MEMF_CLEAR) ; 
time3=(struct timeval *)AllocMem(sizeof (struct timeval), 
MEMF_ PUBLIC | MEMF CLEAR) ; 
tr=(struct timerequest *)AllocMem(sizeof (struct timerequest), 
MEMF PUBLIC | MEMF_ CLEAR); 
/* Make sure we got the memory */ 
if(!timel | !time2 | !time3 | !tr) goto cleanexit; 


/* Set up values to test time arithmetic with. In a real application these */ 
/* values might be filled in via the GET_SYSTIME command of the timer device */ 


JRosnccecsi 2522 boss lees ce seo eee tees les Sok ese seoe alle est ce ck */ 
timel->tv_secs = 3; timel->tv_micro = 0; /* 3.0 seconds */ 
time2->tv_secs = 2;  time2->tv_micro = 500000; /* 2.5 seconds */ 
time3->tv_secs = 1; time3->tv_micro = 900000; /* 1.9 seconds */ 


printf ("Timel is tld.%ld\n" , timel->tv_secs,timel->tv_micro); 
printf ("Time2 is %ld.tld\n" , time2->tv_secs,time2->tv_micro); 
printf ("Time3 is %ld.%ld\n\n",time3->tv_secs,time3->tv_micro); 


/* ween enw ee en eee ee */ 
hs Open the MICROHZ timer device */ 
a eee tobe Soe as Se ae */ 


error = OpenDevice (TIMERNAME, UNIT _MICROHZ, (struct IORequest *) tr, OL); 
if(error) goto cleanexit; 


/* Set up to use the special time arithmetic functions */ 
TimerBase = (struct Library *)tr->tr_node.io Device; 


[Wotan esses Sa aa eee ce oa sees eS so Soe Sb eet See ee ee ace e ass */ 
/* Now that TimerBase is initialized, it is permissible to call the */ 
/* time-comparison or time-arithmetic routines. Result of this example */ 
/* is -1 which means the first parameter has greater time value than second */ 
i parameter; +1 means the second parameter is bigger; 0 means equal. */ 

Wee ewe ww ew mw ew ww ww ww wn nn ee ewe ww ee we ee ew ew wm ww www wen we eo ww we nw em eww we eee x/ 


result = CmpTime( timel, time2 ); 
printf ("Timel and Time2 compare = %ld\n", result); 


/* Add time2 to timel, result in timel */ 
AddTime( timel, time2); 
printf ("Timel + Time2 = %ld.%ld\n",timel->tv_secs,timel->tv_micro); 


/* Subtract time3 from time2, result in time2 */ 
SubTime( time2, time3); 
printf ("Time2 - Time3 = %ld.%ld\n",time2->tv_secs,time2->tv_micro); 


eicanesit: 

if (timel) 

FreeMem(timel, sizeof (struct timeval)); 
if (time2) 

FreeMem(time2, sizeof (struct timeval)); 
if (time3) 

FreeMem(time3, sizeof (struct timeval)); 
if (!error) 

CloseDevice((struct IORequest *) tr); 
if (tr) 

FreeMem(tr,sizeof(struct timerequest) ); 


296 Amiga ROM Kernel Reference Manual: Devices 


WHY USE TIME ARITHMETIC? 


As mentioned earlier in this section, because of the multitasking capability of the Amiga, the timer 
device can provide timings that are at least as long as the specified amount of time. If you need 
more precision than this, using the system timer along with the time arithmetic routines can at least, 
in the long run, let you synchronize your software with this precision timer after a selected period 
of time. 


Say, for example, that you select timer intervals so that you get 161 signals within each 3-minute 
span. Therefore, the timeval you would have selected would be 180/161, which comes out to 1 
second and 118,012 microseconds per interval. Considering the time it takes to set up a call to set 
the timer and delays due to task-switching (especially if the system is very busy), it is possible that 
after 161 timing intervals, you may be somewhat beyond the 3-minute time. Here is a method you 
can use to keep in sync with system time: 


1. Begin. 

2. Read system time; save it. 

3. Perform your loop however many times in your selected interval. 
4 


. Read system time again, and compare it to the old value you saved. (For this example, it will 
be more or less than 3 minutes as a total time elapsed.) 


5. Calculate a new value for the time interval (timeval); that is, one that (if precise) would put 
you exactly in sync with system time the next time around. Timeval will be a lower value if 
the loops took too long, and a higher value if the loops didn’t take long enough. 


6. Repeat the cycle. 


Over the long run, then, your average number of operations within a specified period of time can 
become precisely what you have designed. 


You Can’t Do 1+1 on E-Clock Values. The arithmetic functions are not designed to 
operate on EClockVals. 


Timer Device 297 


E-Clock Time and Its Relationship to Actual Time 


Unlike GetSysTime(), the two values returned by ReadEClock()—tics/sec and the EClockVal 
structure—have no direct relationship to actual time. The tics/sec is the E-Clock count rate, a value 
which is related to the system master clock. The EClock Val structure is simply the upper longword 
and lower longword of the E-Clock 64 bit register. 


However, when two EClockVal structures are subtracted from each other and divided by the 
tics/sec (which remains constant), the result does have a relationship to actual time. The value of 
this calculation is a measure of fractions of a second that passed between the two readings. 


/* E-Clock Fractions of a second fragment 

This fragment reads the E-Clock twice and subtracts the two ev_lo values 
time2->ev_lo - timel->ev_lo 

and divides the result by the E-Clock tics/secs returned by ReadEClock () 

to get the fractions of a second 


/ 


% oF 0 OO 


struct EClockVal *timel, *time2; 
ULONG E_ Freq; 

LONG error; 

struct timerequest *TimerI0; 


TimerIO = (struct timerequest *)AllocMem(sizeof (struct timerequest ), 
MEMF CLEAR | MEMF PUBLIC); 


timel = (struct EClockVal *)AllocMem(sizeof (struct EClockVal ), 
MEMF_CLEAR | MEMF_ PUBLIC); 


time2 = (struct EClockVal *)AllocMem(sizeof (struct EClockVal ), 
MEMF_ CLEAR | MEMF_PUBLIC); 


if (! (error = OpenDevice (TIMERNAME, UNIT_ECLOCK, (struct IORequest *)TimerIO,0L)) ) 
{ 


TimerBase = (struct Library *) TimerIO->tr_node.io Device; 
E_Freq = ReadEClock((struct EClockVal *) timel); /* Get initial reading */ 


/* place operation to be measured here */ 


E_Freq = ReadEClock((struct EClockVal *) time2); /* Get second reading */ 
printf("\nThe operation took: %f fractions of a second\n", 
(time2->ev_lo-timel->ev_lo) /(double)E Frea); 


CloseDevice( (struct IORequest *) TimerIO ); 


} 


The Code Takes Some Liberties. The above fragment only uses the lower longword 
of the EClock Val structures in calculating the fractions of a second that passed. This was 
done to simplify the fragment. Naturally, you would have to at least check the values of 
the upper longwords if not use them to get an accurate measure. 


298 Amiga ROM Kernel Reference Manual: Devices 


Example Timer Program 


Here is an example program showing how to use the timer device. 


/* Simple _Timer.c 


A simple example of using the timer device. 


Run from CLI only 
/ 


#include <exec/types.h> 
#include <exec/io.h> 
#include <exec/memory.h> 
#include <devices/timer.h> 


* 
* 
* 
* 
* Compile with SAS C 5.10: LC -bl -cfistq -v -y -L 
* 
* 
* 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/dos_protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


/* Our timer sub-routines */ 

void delete timer (struct timerequest *); 

LONG get_sys_ time (struct timeval *); 

LONG set_new time (LONG); 

void wait_for timer(struct timerequest *, struct timeval *); 
LONG time_delay ( struct timeval *, LONG ); 

struct timerequest *create timer( ULONG ); 

void show_time (ULONG) ; 


struct Library *TimerBase; /* to get at the time comparison functions */ 


/* manifest constants -- "will never change" */ 
#define SECSPERMIN (60) 

#define SECSPERHOUR (60*60) 

#define SECSPERDAY (60*60*24) 


void main(int argc,char **argv) 


{ 

LONG seconds; 

struct timerequest *tr; /* IO block for timer commands */ 
struct timeval oldtimeval; /* timevals to store times */ 
struct timeval mytimeval; 

struct timeval currentval; 


printf("\nTimer test\n"); 


/* sleep for two seconds */ 
currentval.tv_secs = 2; 
currentval.tv_micro = 0; 

time_delay( &currentval, UNIT _VBLANK ); 
printf( "After 2 seconds delay\n" ); 


/* sleep for four seconds */ 
currentval.tv_secs = 4; 
currentval.tv_micro = 0; 

time delay( &currentval, UNIT _VBLANK ); 
printf( "After 4 seconds delay\n" ); 


/* sleep for 500,000 micro-seconds = 1/2 second */ 
currentval.tv_secs = 0; 

currentval.tv_micro = 500000; 

time_delay( &currentval, UNIT MICROHZ ); 

printf( "After 1/2 second delay\n" ); 


printf( "DOS Date command shows: " ); 
(void) Execute( "date", 0, 0 ); 


Timer Device 299 


/* save what system thinks is the time....we’ll advance it temporarily */ 
get_sys time( s&0ldtimeval ); 

printf("Original system time is:\n"); 

show_time(oldtimeval.tv_secs ); 


printf("Setting a new system time\n"); 
seconds = 1000 * SECSPERDAY + oldtimeval.tv_secs; 
set_new_time( seconds ); 


/* (if user executes the AmigaDOS DATE command now, he will*/ 
/* see that the time has advanced something over 1000 days */ 
printf( "DOS Date command now shows: " ); 

(void) Execute( "date", 0, 0 ); 


get_sys time( &mytimeval ); 
printf( "Current system time is:\n"); 
show_time (mytimeval.tv_secs); 


/* Added the microseconds part to show that time keeps */ 

/* increasing even though you ask many times in a row */ 

printf ("Now do three TR_GETSYSTIMEs in a row (notice how the microseconds increase) \n\n"); 
get_sys_time( &mytimeval ); 

printf ("First TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro); 

get_sys_ time( &mytimeval ); 

printf ("Second TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro); 

get_sys_ time( &mytimeval ); 

printf ("Third TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro); 


printf( "\nResetting to former time\n" ); 
set_new _time( oldtimeval.tv_secs ); 


get_sys time( &mytimeval ); 
printf( "Current system time is:\n"); 
show_time (mytimeval.tv_secs); 


/* just shows how to set up for using the timer functions, does not */ 


/* demonstrate the functions themselves. (TimerBase must have a */ 
/* legal value before AddTime, SubTime or CmpTime are performed. x/ 
tr = create timer( UNIT MICROHZ ); 

TimerBase = (struct Library *)tr->tr_node.io Device; 


/* and how to clean up afterwards */ 
TimerBase = (struct Library *) (-1); 
delete _timer( tr ); 


} 


struct timerequest *create timer( ULONG unit ) 

( = 

/* return a pointer to a timer request. If any problem, return NULL */ 
LONG error; 

struct MsgPort *timerport; 

struct timerequest *TimerI0O; 


timerport = CreatePort( 0, 0 ); 
if (timerport == NULL ) 
return( NULL ); 


TimerIO = (struct timerequest *) 
CreateExtIO( timerport, sizeof( struct timerequest ) ); 
if (TimerIO == NULL ) 


DeletePort (timerport) ; /* Delete message port */ 
return( NULL ); 
} 


error = OpenDevice( TIMERNAME, unit, (struct IORequest *) TimerIO, OL ); 
if (error !=0 ) 

{ 

delete timer( TimerIO ); 

return( NULL ); 

} 


return( TimerIO ); 


300 Amiga ROM Kernel Reference Manual: Devices 


/* more precise timer than AmigaDOS Delay() */ 

LONG time_delay( struct timeval *tv, LONG unit ) 

{ 

struct timerequest *tr; 

/* get a pointer to an initialized timer request block */ 
tr = create _timer( unit ); 


/* any nonzero return says timedelay routine didn’t work. */ 
if (tr == NULL ) 
return( -1L ); 


wait_for timer( tr, tv ); 


/* deallocate temporary structures */ 
delete _timer( tr ); 
return( OL ); 


} 


void wait for timer(struct timerequest *tr, struct timeval *tv ) 


{ 
tr->tr_node.io Command = TR_ADDREQUEST; /* add a new timer request */ 


/* structure assignment */ 
tr->tr_time = *tv; 


/* post request to the timer -- will go to sleep till done */ 
DoIO((struct IORequest *) tr ); 
} 


LONG set_new_time(LONG secs) 

{ 

struct timerequest *tr; 

tr = create _timer( UNIT MICROHZ ); 


/* non zero return says error */ 
if (tr == 0 ) 
return( -1 ); 


tr->tr_time.tv_secs = secs; 
tr->tr_time.tv_micro = 0; 
tr->tr_node.io Command = TR_SETSYSTIME; 
DoIO((struct IORequest *) tr ); 


delete timer(tr); 
return (0); 


LONG get_sys_time(struct timeval *tv) 
{ 


struct timerequest *tr; 
tr = create_timer( UNIT MICROHZ ); 


/* non zero return says error */ 
if (tr == 0 ) 
return( -1 ); 


tr->tr_node.io Command = TR_GETSYSTIME; 
DoIO((struct IORequest *) tr ); 


/* structure assignment */ 
*tv = tr->tr_time; 


delete _timer( tr ); 
return( 0 ); 


Timer Device 301 


void delete timer(struct timerequest *tr ) 
{ 
struct MsgPort *tp; 
if (tr !=0 ) 
{ 
tp = tr->tr_node.io Message.mn_ReplyPort; 


if (tp != 0) 
DeletePort (tp); 


CloseDevice( (struct IORequest *) tr ); 
DeleteExtIO( (struct IORequest *) tr ); 
} 


void show _time(ULONG secs) 
{ 
ULONG days,hrs,mins; 


/* Compute days, hours, etc. */ 
mins=secs/60; 

hrs=mins/60; 

days=hrs/24; 

secs=secs%60; 

mins=mins%60; 

hrs=hrs%24; 


/* Display the time */ 
printf ("* Hour Minute Second (Days since Jan.1,1978)\n"); 


printf ("*%51d:%51d:%5ld ($61d )\n\n",hrs,mins, secs, days) ; 
} /* end of main */ 


Additional Information on the Timer Device 


Additional programming information on the timer device and the utilities library can be found in 
their include files and Autodocs. All are contained in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs. 


Timer Device Information 


INCLUDES devices/timer.h 
devices/timer.i 


utility/date.h 
utility/date.i 


AUTODOCS timer.doc 
utility.doc 





302 Amiga ROM Kernel Reference Manual: Devices 


chapter fourteen 
TRACKDISK DEVICE 


The Amiga trackdisk device directly drives the disk, controls the disk motors, reads raw data from 
the tracks, and writes raw data to the tracks. Normally, you use the AmigaDOS functions to write or 
read data from the disk. The trackdisk device is the lowest-level software access to the disk data and 
is used by AmigaDOS to access the disks. The trackdisk device supports the usual commands such 
as CMD_WRITE and CMD_READ. In addition, it supports an extended form of these commands 
to allow additional control over the trackdisk device. 


New Features for Version 2.0 
Feature Description 


TD_GETGEOMETRY Device Command 


TD_EJECT Device Command 
IOTF_INDEXSYNC Device Command Flag 
IOTF_WORDSYNC Device Command Flag 
Fast RAM Buffers Now Supported 





Compatibility Warning: The new features for 2.0 are not backwards compatible. 


Trackdisk Device 303 


Trackdisk Device Commands and Functions 


Command 


CMD_CLEAR 
ETD_CLEAR 


CMD_READ 
ETD_READ 


CMD_UPDATE 
ETD_UPDATE 


CMD_WRITE 
ETD_WRITE 


TD_ADDCHANGEINT 
TD_CHANGENUM 


TD_CHANGESTATE 
TD_EJECT 


TD_FORMAT 
ETD_FORMAT 


TD_GETDRIVETYPE 
TD_GETGEOMETRY 
TD_GETNUMTRACKS 


TD_MOTOR 
ETD_MOTOR 


TD_PROTSTATUS 


TD_RAWREAD 
ETD_RAWREAD 


TD_RAWWRITE 
ETD_RAWWRITE 


TD_REMCHANGEINT 


TD_SEEK 
ETD_SEEK 


Operation 


Mark track buffer as invalid. Forces the track to be re-read. 
ETD_CLEAR also checks for a diskchange. 


Read one or more sectors from a disk. ETD_READ also reads the 
sector label area and checks for a diskchange. 


Write out track buffer if it has been changed. ETD_UPDATE also 
checks for a diskchange. 


Write one or more sectors to a disk. ETD_WRITE also writes the 
sector label area and checks for a diskchange. 


Add an interrupt handler to be activated on a diskchange. 


Retum the current value of the diskchange counter used by the 
ETD commands to determine if a diskchange has occurred. 


Retum the disk present/not-present status of a drive. 


Eject a disk from a drive. This command will only work on drives 
that support an eject command (V36). 


Initialize one or more tracks with a data buffer. ETD_FORMAT 
also initializes the sector label area. 


Retum the type of disk drive in use by the unit. 
Retum the disk geometry table (V36). 
Retum the number of tracks usable with the unit. 


Tum the motor on or off. ETD_MOTOR also checks for a 
diskchange. 


Return the write-protect status of a disk. 


Read RAW sector data from disk (unencoded MFM). 
ETD_RAWREAD also checks for a diskchange. 


Write RAW sector data to disk. ETD-RAWWRITE also checks 
for a diskchange. 


Remove a diskchange interrupt handler. 


Move the head to a specific track. ETD_SEEK also checks for a 
diskchange. 


304 Amiga ROM Kernel Reference Manual: Devices 


Exec Functions as Used In This Chapter 


AbortIOQ Abort a command to the trackdisk device. 

BeginIO() Initiate a command and return immediately (asynchronous request). 
CloseDevice() Relinquish use of a disk unit. 

DoIOO Initiate a command and wait for completion (synchronous request). 
OpenDevice() Obtain exclusive use of a particular disk unit. 


Exec Support Functions as Used in This Chapter 


CreateExtIO() Create an extended I/O request structure of type [OExtTD. This structure will 
be used to communicate commands to the trackdisk device. 

CreatePort() Create a signal message port for reply messages from the trackdisk device. 
Exec will signal a task when a message arrives at the reply port. 

DeleteExtIO() Delete an I/O request structure created by CreateExtIO(). 

DeletePort() Delete the message port created by CreatePort(). 


Device Interface 


The trackdisk device operates like other Amiga devices. To use it, you must first open the device, 
then send I/O requests to it, and then close it when finished. See the “Introduction to Amiga System 
Devices” chapter for general information on device usage. 


The trackdisk device uses two different types of I/O request blocks, [OStdReq and IOExtTD and 
two types of commands, standard and extended. An IOExtTD is required for the extended trackdisk 
commands (those beginning with “ETD_”), but can be used for both types of commands. Thus, the 
IOExtTD is the type of I/O request that will be used in this chapter. 


struct IOExtTD 
{ 


struct IOStdReq iotd_Req; 

ULONG iotd_ Count; /* Diskchange counter */ 

ULONG iotd_ SecLabel; /* Sector label data */ 
‘; 


See the include file devices/trackdisk.h for the complete structure definition. 


The enhanced commands listed above—those beginning with “ETD_”’— are similar to their standard 
counterparts but have additional features: they allow you to control whether a command will be 
executed if the disk has been changed and they allow you to read or write to the sector label portion 
of a sector. 


Enhanced commands require a larger I/O request, IOExtTD, than the [OStdReq request used by 
the standard commands. IOExtTD contains extra information needed by the enhanced command; 
since the standard form of a command ignores the extra fields, IOExtTD requests can be used for 
both types. The extra information takes the form of two extra longwords at the end of the data 
structure. These commands are performed only if the change count is less than or equal to the value 
in the iotd_Count field of the command’s request block. 


Trackdisk Device 305 


The iotd_Count field keeps old I/O requests from being performed when the disk is changed. Any 
request found with an iotd_Count less than the current change counter value will be returned with 
a characteristic error (TDERR_DiskChange) in the io_Error field. This allows stale I/O requests to 
be retumed to the user after a disk has been changed. The current disk-change counter value can be 
obtained by TD_CHANGENUM. If the user wants enhanced disk I/O but does not care about disk 
removal, then iotd_Count may be set to the maximum unsigned long integer value (OxFFFFFFFF). 


The iotd_SecLabel field allows access to the sector identification section of the sector header. Each 
sector has 16 bytes of descriptive data space available to it; the trackdisk device does not interpret 
this data. If iotd_SecLabel is NULL, then this descriptive data is ignored. If it is not NULL, then 
iotd_SecLabel should point to a series of contiguous 16-byte chunks (one for each sector that is to 
be read or written). These chunks will be written out to the sector’s label region on a write or filled 
with the sector’s label area on a read. If a CMD_WRITE (the standard write call) is done, then the 
sector label area is left unchanged. 


ABOUT AMIGA FLOPPY DISKS 


The standard 3.5 inch Amiga floppy disk consists of a number of tracks that are NUMSECS (11) 
sectors of TD_SECTOR (512) usable data bytes plus TD_LABELSIZE (16) bytes of label area. 
There are usually 2 tracks per cylinder (2 heads) and 80 cylinders per disk. The number of tracks 
can be found using the TD_GETNUMTRACKS command. 


For V36 and higher systems, the NUMSECS in some drives may be variable and may change when 
a disk is inserted. Use TD_GETGEOMETRY to determine the current number of sectors. 


Think Tracks not Cylinders. The result is given in tracks and not cylinders. On a 
standard 3.5" drive, this gives useful space of 880K bytes plus 28K bytes of sector label 
area per floppy disk. 


Although the disk is logically divided up into sectors, all I/O to the disk is done a track at a time. 
This allows access to the drive with no interleaving and increases the useful storage capacity by 
about 20 percent. Each disk drive on the system has its own buffer which holds the track data going 
to and from the drive. 


Normally, a read of a sector will only have to copy the data from the track buffer. If the track buffer 
contains another track’s data, then the buffer will first be written back to the disk (if it is “dirty”) 
and the new track will be read in. All track boundaries are transparent to the programmer (except 
for FORMAT, SEEK, and RAWREAD/RAWWRITE commands) because you give the device an 
offset into the disk in the number of bytes from the start of the disk. The device ensures that the 
correct track is brought into memory. 


The performance of the disk is greatly enhanced if you make effective use of the track buffer. The 
performance of sequential reads will be up to an order of magnitude greater than reads scattered 
across the disk. In addition, only full-sector writes on sector boundaries are supported. 


The trackdisk device is based upon a standard device structure. It has the following restrictions: 


e All reads and writes must use an io_Length that is an integer multiple of TD_SECTOR bytes 
(the sector size in bytes). 


e The offset field must be an integer multiple of TD_SECTOR. 
e The data buffer must be word-aligned. 
e Under pre-V36, the data buffer must be also be in Chip RAM. 


306 Amiga ROM Kernel Reference Manual: Devices 


OPENING THE TRACKDISK DEVICE 


Three primary steps are required to open the trackdisk device: 


e Create a message port by calling CreatePort(). Reply messages from the device must be 
directed to a message port. 


e Create an extended I/O request structure of type IOExtTD. The IOExtTD structure is created 
by the CreateExtIO() function. 


e Open the trackdisk device. Call OpenDevice(), passing it the extended I/O request. 


For the trackdisk device, the flags parameter of the OpenDevice() function specifies whether you 
are opening a 3.5" drive (flags=0) or a 5.25" drive (flags=1). With flags set to 0 trackdisk will only 
open a 3.5" drive. To tell the device to open any drive it understands, set the flags parameter to 
TDF_ALLOW_NON_3_5. (See the include file devices/trackdisk.h for more information.) 


#include <devices/trackdisk.h> 


struct MsgPort *TrackMP; /* Pointer for message port */ 
struct IOExtTD *TrackIO; /* Pointer for I0Request */ 


if (TrackMP=CreatePort (0,0) ) 
if (TrackIO=(struct IOExtTD *) 
CreateExtI0O(TrackMP, sizeof (struct IOExtTD)) ) 
if (OpenDevice (TD NAME, OL, (struct IORequest *)TrackIO,Flags) ) 
printf("%s did not open\n", TD_NAME) ; 


Disk Drive Unit Numbers. The unit number—second parameter of the OpenDevice() 
call—can be any value from 0 to 3. Unit 0 is the built-in 3.5" disk drive. Units 1 through 
3 represent additional disk drives that may be connected to an Amiga system. 


READING FROM THE TRACKDISK DEVICE 


You read from the trackdisk device by passing an IOExtTD to the device with CMD_READ set in 
io_Command, the number of bytes to be read set in io_Length, the address of the read buffer set 
in io_Data and the track you want to read—specified as a byte offset from the start of the disk—set 
in io_Offset. 


The byte offset of a particular track is calculated by multiplying the number of the track you want 
to read by the number of bytes in a track. The number of bytes in a track is obtained by multiplying 
the number of sectors (NUMSECS) by the number of bytes per sector (TD_SECTOR). Thus you 
would multiply 11 by 512 to get 5632 bytes per track. To read track 15, you would multiply 15 by 
5632 giving 84,480 bytes offset from the beginning of the disk. 

#define TRACK SIZE ((LONG) (NUMSECS * TD_SECTOR) ) 


UBYTE *Readbuf fer; 
SHORT tracknum; 


if (Readbuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF_CHIP) ) 
{ 


DiskIO->iotd Req.io_Length = TRACK_SIZE; 
DiskIO->iotd_Req.io Data = (APTR)Readbuffer; 
DiskIO->iotd | | Req.io . Offset = (ULONG) (TRACK_SIZE * track); 
DiskIO->iotd_Req.io Command = CMD READ; 

DoIO((struct IORequest *)DiskIO); 

} 


Trackdisk Device 307 


For reads using the enhanced read command ETD_READ, the IOExtTD is set the same as above 
with the addition of setting iotd_Count to the current diskchange number. The diskchange number 
is retumed by the TD_CHANGENUM command (see below). If you wish to also read the sector 
label area, you must set iotd_SecLabel to a non-NULL value. 


DiskIO->iotd_Req.io Length = TRACK_SIZE; 

DiskI0O->iotd_ Req.io Data = (APTR)Readbuffer; 
DiskIO->iotd Req.io Offset = (ULONG) (TRACK_SIZE * track); 
DiskIO->iotd_ Count = change_count; 

DiskIO->iotd Req.io Command = ETD READ; 


DoIO((struct IORequest *)DiskIO); _ 


| 


ETD_READ and CMD_READ obey all of the trackdisk device restrictions noted above. They 
transfer data from the track buffer to the user’s buffer. If the desired sector is already in the track 
buffer, no disk activity is initiated. If the desired sector is not in the buffer, the track containing that 
sector is automatically read in. If the data in the current track buffer has been modified, it is written 
out to the disk before a new track is read. 


WRITING TO THE TRACKDISK DEVICE 


You write to the trackdisk device by passing an IOExtTD to the device with CMD_WRITE set in 
io_Command, the number of bytes to be written set in io_Length, the address of the write buffer 
set in io_Data and the track you want to write—specified as a byte offset from the start of the 
disk—-set in io_Offset. 


#define TRACK SIZE ((LONG) (NUMSECS * TD_SECTOR) ) 
UBYTE *Writebuffer; 


if (Writebuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF_PUBLIC) ) 


{ 

DiskIO->iotd_Req.io Length = TRACK_SIZE; 

DiskIO->iotd Req.io Data = (APTR)Writebuffer; 

DiskIO->iotd Req.io Offset = (ULONG) (TRACK_SIZE * tracknum); 
DiskIO->iotd_Req.io Command = CMD WRITE; 

DoIO((struct IORequest *)DiskIO); 

} 


For writes using the enhanced write command ETD_WRITE, the IOExtTD is set the same as above 
with the addition of setting iotd_Count to the current diskchange number. The diskchange number 
is returned by the TD_CHANGENUM command (see below). If you wish to also write the sector 
label area, you must set iotd_SecLabel to a non-NULL value. 

DiskIO->iotd Req.io_ Length = TRACK SIZE; 

DiskIO->iotd_Req.io Data = (APTR)Writebuffer; 

DiskIO->iotd Req.io Offset = (ULONG) (TRACK_SIZE * tracknum); 

DiskIO->iotd Count = change count; 


DiskIO->iotd_Req.io Command = ETD WRITE; 
DoIO((struct IORequest *)DiskIO); 


ETD_WRITE and CMD_WRITE obey all of the trackdisk device restrictions noted above. They 
transfer data from the user’s buffer to the track buffer. If the track that contains this sector is already 
in the track buffer, no disk activity is initiated. If the desired sector is not in the buffer, the track 
containing that sector is automatically read in. If the data in the current track buffer has been 
modified, it is written out to the disk before a new track is read in for modification. 


308 Amiga ROM Kernel Reference Manual: Devices 


CLOSING THE TRACKDISK DEVICE 


As with all devices, you must close the trackdisk device when you have finished using it. To release 
the device, a CloseDevice() call is executed with the same IOExtTD used when the device was 
opened. This only closes the device and makes it available to the rest of the system. It does not 
deallocate the I[OExtTD structure. 


CloseDevice((struct IORequest *) DiskIO); 


Advanced Commands 


DETERMINING THE DRIVE GEOMETRY TABLE 
The layout geometry of a disk drive can be determined by using the TD_GETGEOMETRY com- 
mand. The layout can be defined three ways: 

e TotalSectors 

e Cylinders and CylSectors 


e Cylinders, Heads, and TrackSectors. 


Of the three, TotalSectors is the most accurate, Cylinders and CylSectors is less so, and Cylinders, 
Heads and TrackSectors is the least accurate. All are usable, though the last two may waste some 
portion of the available space on some drives. 


The TD_GETGEOMETRY commands retums the disk layout geometry in a DriveGeometry 
structure: 


struct DriveGeometry 


ULONG dg SectorSize; /* in bytes */ 
ULONG dg TotalSectors; /* total # of sectors on drive */ 
ULONG dg Cylinders; /* number of cylinders */ 
ULONG dg CylSectors; /* number of sectors/cylinder */ 
ULONG dg Heads; /* number of surfaces */ 
ULONG dg_TrackSectors; /* number of sectors/track */ 
ULONG dg_BufMemType; /* preferred buffer memory type */ 
/* (usually MEMF_PUBLIC) */ 
UBYTE dg DeviceType; /* codes as defined in the SCSI-2 spec*/ 
UBYTE dg Flags; /* flags, including removable */ 


UWORD dg Reserved; 
Me 


See the include file devices/trackdisk.h for the complete structure definition and values for the 
dg_DeviceType and dg_Flags fields. 


You determine the drive layout geometry by passing an IOExtTD with TD_GETGEOMETRY set 
in io_Command and a pointer to a DriveGeometry structure set in io_Data. 
struct DriveGeometry *Euclid; 


Euclid = (struct DriveGeometry *) 
AllocMem(sizeof (struct DriveGeometry) ,MEMF_PUBLIC | MEMF_CLEAR) ; 


DiskI0O->iotd_Req.io Data = Euclid; /* put layout geometry here */ 


DiskI0->iotd_Req.io Command = TD_GETGEOMETRY; 
DoIO((struct IORequest *)DiskIO); 


Trackdisk Device 309 


For V36 and higher versions of the operating system, TD_GETGEOMETRY is preferred over 
TD_GETNUMTRACKS for determining the number of tracks on a disk. This is because new drive 
types may have more sectors or different sector sizes, etc., than standard Amiga drives. 


CLEARING THE TRACK BUFFER 


ETD_CLEAR and CMD_CLEAR mark the track buffer as invalid, forcing a reread of the disk on 
the next operation. ETD_UPDATE or CMD_UPDATE would be used to force data out to the disk 
before tuming the motor off. ETD_CLEAR or CMD_CLEAR is usually used after having locked 
out the trackdisk device via the use of the disk resource, when you wish to prevent the track from 
being updated, or when you wish to force the track to be re-read. ETD_CLEAR or CMD_CLEAR 
will not do an update, nor will an update command do a clear. 


You clear the track buffer by passing an IOExtTD to the device with CMD_CLEAR or 
ETD_CLEAR set in io_Command. For ETD_CLEAR, you must also set iotd_Count to the 
current diskchange number. 


DiskIO->iotd_Req.io_ Command = TD_CLEAR; 
DoIO((struct IORequest *)DiskIO); 


CONTROLLING THE DRIVE MOTOR 


ETD_MOTOR and TD_MOTOR give you control of the motor. When the trackdisk device executes 
this command, the old state of the motor is retumed in io_Actual. If io_Actual is zero, then the 
motor was off. Any other value implies that the motor was on. If the motor is just being turned on, 
the device will delay the proper amount of time to allow the drive to come up to speed. Normally, 
tuming the drive on is not necessary—the device does this automatically if it receives a request 
when the motor is off. 


However, tuming the motor off is the programmer’s responsibility. In addition, the standard 
instructions to the user are that it is safe to remove a disk if, and only if, the motor is off (that is, if 
the disk light is off). 


You control the drive motor by passing an IOExtTD to the device with CMD_MOTOR or 
ETD_MOTOR set in io_Command and the state you want to put the motor in set in io_Length. 
If io_Length is set to 1, the trackdisk device will tum on the motor; a 0 will tum it off. For 
ETD_MOTOR, you must also set iotd_Count to the current diskchange number. 

DiskIO->iotd_ Req.io Length = 1; /* Turn on the drive motor */ 


DiskIO->iotd_Req.io Command = TD_ MOTOR; 
DoIO((struct IORequest *)DiskIO); 


UPDATING A TRACK SECTOR 


The Amiga trackdisk device does not write data sectors unless it is necessary (you request that a 
different track be used) or until the user requests that an update be performed. This improves system 
speed by caching disk operations. The update commands ensure that any buffered data is flushed 
out to the disk. If the track buffer has not been changed since the track was read in, the update 
commands do nothing. 


310 Amiga ROM Kernel Reference Manual: Devices 


You update a data sector by passing an IOExtTD to the device with CMD_UPDATE or 
ETD_UPDATE set in io_Command. For ETD_UPDATE, you must also set iotd_Count to 
the current diskchange number. 


DiskI0O->iotd_Req.io_Command = TD_UPDATE; 
DoIO((struct IORequest *)DiskIO);_ 


FORMATTING A TRACK 


ETD_FORMAT and TD_FORMAT are used to write data to a track that either has not yet been 
formatted or has had a hard error on a standard write command. TD_FORMAT completely ignores 
all data currently on a track and does not check for disk change before performing the command. 
The device will format the requested tracks, filling each sector with the contents of the buffer pointed 
to by io_Data field. You should do a read pass to verify the data. 


If you have a hard write error during anormal write, you may find it possible to use the TD_FORMAT 
command to reformat the track as part of your error recovery process. ETD_FORMAT will write 
the sector label area if the iotd_SecLabel is non-NULL. 


You format a track by passing an IOExtTD to the device with CMD_FORMAT or ETD_FORMAT 
set in io_Command, io_Data set to at least track worth of data, io_Offset field set to the byte offset 
of the track you want to write and the io_Length set to the length of a track. For ETD_FORMAT, 
you must also set iotd_Count to the current diskchange number. 


#define TRACK SIZE ((LONG) (NUMSECS * TD | SECTOR) ) 
UBYTE *Writebuffer; 


if (WriteBuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF CHIP) ) 
{ 
DiskI0->iotd_Req.io_Length=TRACK_SIZE; 
DiskIO->iotd_Req.io Data=(APTR)Writebuffer; 
DiskIO->iotd |] | Req.io . Of fset=(ULONG) (TRACK_SIZE * track); 


DiskIO->iotd_Req.io Command = TD_FORMAT; 
DoIO((struct IORequest *)DiskIO); 
} 


EJECTING A DISK 


Certain disk drive manufacturers allow software control of disk ejection. The trackdisk device 
provides the TD_EJECT command to tell such drives to eject a disk. 


You eject a disk by passing an IOExtTD to the device with TD_EJECT set in io_Command. 


DiskIO->iotd_Req.io Command = TD EJECT; 
DoIO((struct IORequest *)DiskIO);_ 


Read the Instruction Manual. The Commodore 3.5" drives for the Amiga and most 
other Amiga drive manufacturers do not support software disk ejects. Attempting this 
command on those drives will result in an error condition. Consult the instruction manual 
for your disk drive to determine whether this is supported. 


Trackdisk Device 311 


Disk Status Commands 


Disk status commands retum status on the current disk in the opened unit. These commands may 
be done with quick I/O and thus may be called within interrupt handlers (such as the trackdisk 
disk change handler). See the “Exec: Device Input/Output” chapter of the Amiga ROM Kernel 
Reference Manual: Libraries for more detailed information on quick I/O. 


DETERMINING THE PRESENCE OF A DISK 


You determine the presence of a disk in a drive by passing an IOExtTD to the device with 
TD_CHANGESTATE set in io_Command. For quick I/O, you must set io_Flags to IOF_QUICK. 
DiskIO->iotd Req.io Flags = IOF QUICK; 


DiskIO->iotd Req.io Command = TD_CHANGESTATE; 
BeginIO((struct IORequest *)DiskIO); 


TD_CHANGESTATE retums the presence indicator of a disk in io_Actual. The value retumed 
will be zero if a disk is currently in the drive and nonzero if the drive has no disk. 


DETERMINING THE WRITE-PROTECT STATUS OF A DISK 


You determine the write-protect status of a disk by passing an IOExtTD to the device with 
TD_PROTSTATUS set in io_Command. For quick I/O, you must set io_Flags to IOF_QUICK. 
DiskI0->iotd_Req.io Flags = IOF_QUICK; 


DiskIO->iotd_Req.io Command = TD_PROTSTATUS; 
BeginIO((struct IORequest *)DiskIO); 


TD_PROTSTATUS returns the write-protect status in io_Actual. The value will be zero if the disk 
is not write-protected and nonzero if the disk is write-protected. 


DETERMINING THE DRIVE TYPE 


You determine the drive type of a unit by passing an IOExtTD to the device with 
TD_GETDRIVETYPE set in io_Command. For quick I/O, you must set io_Flags to IOF_QUICK. 
DiskIO->iotd Req.io Flags = IOF QUICK; 


DiskI0->iotd_Req.io Command = TD_GETDRIVETYPE; 
BeginIO((struct IORequest *)DiskIO); 


TD_GETDRIVETYPE retums the drive type for the unit that was opened in io_Actual. The value 
will be DRIVE3_S for 3.5" drives and DRIVES_25 for 5.25" drives. The unit can be opened only 
if the device understands the drive type it is connected to. 


312 Amiga ROM Kernel Reference Manual: Devices 


DETERMINING THE NUMBER OF TRACKS OF A DRIVE 


You determine the number of a tracks of a drive by passing an IOExtTD to the device 
with TD_GETNUMTRACKS set in io_Command. For quick I/O, you must set io_Flags to 
IOF_QUICK. 

Disk10->iotd_Req.io Flags = IOF_QUICK; 


DiskIO->iotd_Req.io Command = TD_GETNUMTRACKS; 
BeginIO((struct IORequest *)DiskIO); 


TD_GETNUMTRACKS retums the number of tracks on that device in io_Actual. This is the 
number of tracks of TD_SECTOR * NUMSECS size. It is not the number of cylinders. With two 
heads, the number of cylinders is half of the number of tracks. The number of cylinders is equal 
to the number of tracks divided by the number of heads (surfaces). The standard 3.5" Amiga drive 
has two heads 


TD_GETGEOMETRY is the preferred over TD_GETNUMTRACKS for V36 and higher versions 
of the operating system especially since new drive types may have more sectors or different sector 
sizes, etc., than standard Amiga drives. 


DETERMINING THE CURRENT DISKCHANGE NUMBER 


You determine the current diskchange number of a disk by passing an IOExtTD to the device with 
TD_CHANGENUM set in io_Command. For quick I/O, you must set io_Flags to IOF_QUICK. 


DiskIO->iotd_Req.io Flags = IOF_QUICK; 
DiskIO->iotd_Req.io Command = TD_CHANGENUM; 
BeginIO((struct IORequest *)DiskIO); 


TD_CHANGENUM retums the current value of the diskchange counter (as used by the enhanced 
commands) in io_Actual. The disk change counter is incremented each time the disk is inserted or 
removed. 


ULONG change_count; 


DiskIO->iotd_Req.io Flags = IOF_QUICK; 

DiskI0->iotd_Req.io Command = TD_CHANGENUM; 

BeginIO((struct IORequest *)DiskIO); 

change_count = DiskIO0->iotd_Req.io_ Actual; /* store current diskchange value */ 


Disk1I0->iotd_Req.io Length = 1; /* Turn on the drive motor */ 
DiskIO->iotd Count = change count; 

DiskIO->iotd_Req.io Command = ETD MOTOR; 

DoIO((struct IORequest *)DiskIO); 


Trackdisk Device 313 


Commands for Diagnostics and Repair 


The trackdisk device provides commands to move the drive heads to a specific track. These 
commands are provided for internal diagnostics, disk repair, and head cleaning only. 


MOVING THE DRIVE HEAD TO A SPECIFIC TRACK 


You move the drive head to a specific track by passing an IOExtTD to the device with TD_SEEK 
or ETD_SEEK set in io_Command, and io_Offset set to the byte offset of the track to which the 
seek is to occur. 

DiskIO->iotd Req.io Offset = (ULONG) (TRACK_SIZE * track); 


DiskIO->iotd_Req.io Command = TD_SEEK; 
DoIO((struct IORequest *)DiskIO); 


Seeking is not Reading. TD _SEEK and ETD_SEEK do not verify their position until 
the next read. That is, they only move the heads; they do not actually read any data. 


Notification of Disk Changes 


Many programs will wish to be notified if the user has changed the disk in the active drive. While 
this can be done via the Intuition DISKREMOVED and DISKINSERTED messages, sometimes 
more tightly controlled testing is required. The trackdisk device provides commands to initiate 
interrupt processing when disks change. 


ADDING A DISKCHANGE SOFTWARE INTERRUPT HANDLER 


The trackdisk device lets you add a software interrupt handler that will be Cause()’ed when a disk 
insert or remove occurs. Within the handler, you may only call the status commands that can use 
IOF_QUICK. 


You add a software interrupt handler by passing an IOExtTD to the device with a pointer 
to an Interrupt structure set in io_Data, the length of the structure set in io_Length and 
TD_ADDCHANGEINT set in io_Command. 

DiskIO->iotd_ Req.io Length = sizeof(struct Interrupt) 

DiskI0O->iotd_Req.io Data = (APTR)Disk Interrupt; 


DiskIO->iotd Req.io Command = TD_ADDCHANGEINT; 
SendIO((struct IORequest *)DiskIO); 


Going, going, gone. This command does not retum when executed. It holds onto 


the IORequest until the TD_LREMCHANGEINT command is executed with that same 
IORequest. Hence, you must use SendIO(Q with this command. 


314 Amiga ROM Kernel Reference Manual: Devices 


REMOVING A DISKCHANGE SOFTWARE INTERRUPT HANDLER 


You remove a software interrupt handler by passing an IOExtTD to the device with a pointer 
to an Interrupt structure set in io_Data, the length of the structure set in io_Length and 
TD_REMCHANGEINT set in io_Command. You must pass it the same Interrupt structure used 
to add the handler. 


DiskI0->iotd_Req.io_ Length = sizeof(struct Interrupt) 
DiskI0->iotd_Req.io Data = (APTR)Disk_Interrupt; 
DiskI0->iotd_Req.io Command = TD_REMCHANGEINT; 
DoIO((struct IORequest *)DiskIO); 


Don't use with pre-V36 and earlier versions. _ Under pre-V36 and earlier versions 
of the Amiga system software, TD_REMCHANGEINT does not work and should not be 
used. Instead, use the workaround listed in the “trackdisk.doc” of the Amiga ROM Kernel 
Reference Manual: Includes and Autodocs. 


Commands for Low-Level Access 


The trackdisk device provides commands to read and write raw flux changes on the disk. The data 
retumed from a low-level read or sent via a low-level write should be encoded into some form 
of legal flux patterns. See the Amiga Hardware Reference Manual and books on magnetic media 
recording and reading. 


Proceed at your own risk with V1.3 and earlier versions. In V1.3 Kickstart and earlier 
these functions are unreliable even though under certain configurations the commands may 
appear to work. 


READING RAW DATA FROM A DISK 


ETD_RAWREAD and TD_RAWREAD perform a raw read from a track on the disk. They seek to 
the specified track and read it into the user’s buffer. 


No processing of the track is done. It will appear exactly as the bits come off the disk — typically 
in some legal flux format (such as MFM, FM, GCR, etc; if you don’t know what these are, you 
shouldn’t be using this call). Caveat programmer. 


This interface is intended for sophisticated programming only. You must fully understand digital 
magnetic recording to be able to utilize this call. It is also important that you understand that the 
MFM encoding scheme used by the higher level trackdisk routines may change without notice. 
Thus, this routine is only really useful for reading and decoding other disks such as MS-DOS 
formatted disks. 


You read raw data from a disk by passing an IOExtTD to the device with TDLRAWREAD or 
ETD_RAWREAD set in io_Command, the number of bytes to be read set in io_Length (maximum 
32K), a pointer to the read buffer set in io_Data, and io_Offset set to the byte offset of the track 
where you want to the read to begin. For ETD_RAWREAD, you must also set iotd_Count to the 
current diskchange number. 


Trackdisk Device 315 


DiskIO->iotd_Req.io Length = 1024; /* number of bytes to read */ 
DiskIO->iotd_Req.io Data = (APTR)Readbuffer; /* pointer to buffer */ 
DiskIO->iotd_Req.io Offset = (ULONG) (TRACK_SIZE * track); /* track number */ 
DiskIO->iotd_Req.io Flags = IOTDF_INDEX /* Set for index sync */ 
DiskIO->iotd Count = change count; /* diskchange number */ 
DiskIO->iotd_Req.io Command = ETD_RAWREAD; 

DoIO((struct IORequest *)DiskIO); 


A raw read may be synched with the index pulse by setting the IOTDF_INDEXSYNC flag or synched 
with a $4489 sync pattem by setting the IOTDF_WORDSYNC flag. See the “trackdisk.doc”’ of the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs for more information about these 
flags. 


Forewarned is Forearmed. | Commodore-Amiga may make enhancements to the 
disk format in the future. Commodore-Amiga intends to provide compatibility within 
the trackdisk device. Anyone who uses these raw routines is bypassing this upward- 
compatibility and does so at her own risk. 


WRITING RAW DATA TO A DISK 


ETD_RAWWRITE and TD_RAWWRITE perform a raw write to a track on the disk. They seek to 
the specified track and write it from the user’s buffer. 


No processing of the track is done. It will be written exactly as the bits come out of the buffer — 
typically in some legal flux format (such as MFM, FM, GCR; if you don’t know what these are, 
you shouldn’t be using this call). Caveat Programmer. 


This interface is intended for sophisticated programming only. You must fully understand digital 
magnetic recording to be able to utilize this call. It is also important that you understand that the 
MFM encoding scheme used by the higher level trackdisk routines may change without notice. 
Thus, this routine is only really useful for encoding and writing other disk formats such as MS-DOS 
disks. 


You write raw data to a disk by passing an IOExtTD to the device with TD_RAWRITE or 
ETD_RAWRITE set in io_Command, the number of bytes to be written set in io_Length (maxi- 
mum 32K), a pointer to the write buffer set in io_Data, and io_Offset set to the byte offset of the 
track where you want to the write to begin. For ETD_RAWWRITE, you must also set iotd_Count 
to the current diskchange number. 

DiskIO->iotd_Req.io Length = 1024; /* number of bytes to write */ 

DiskIO->iotd Req.io Data = (APTR)Writebuffer; /* pointer to buffer */ 

Disk10->iotd_Req.io Offset = (ULONG) (TRACK SIZE * track); /* track number */ 
DiskIO->iotd_Req.io Flags = IOTDF_INDEX /* Set for index sync */ 

DiskIO->iotd Count = change_count; /* diskchange number */ 


DiskIO->iotd_Req.io Command = ETD RAWWRITE; 
DoIO((struct IORequest *)DiskIO); 


A raw read may be synched with the index pulse by setting the IOTDF_INDEXSYNC flag or synched 
with a $4489 sync pattern by setting the IOTDF_WORDSYNC flag. See the “trackdisk.doc” of the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs for more information about these 
flags. 


316 Amiga ROM Kernel Reference Manual: Devices 


LIMITATIONS FOR SYNC’ED READS AND WRITES 


There is a delay between the index pulse and the start of bits coming in from the drive (e.g. 
dma started). It is in the range of 135-200 microseconds. This delay breaks down as follows: 
55 microseconds for software interrupt overhead (this is the time from interrupt to the write of 
the DSKLEN register); 66 microsecs for one horizontal line delay (remember that disk I/O is 
synchronized with Agnus’ display fetches). The last variable (0-65 microseconds) is an additional 
scan line since DSKLEN is poked anywhere in the horizontal line. This leaves 15 microseconds 
unaccounted for. In short, you will almost never get bits within the first 135 microseconds of the 
index pulse, and may not get it until 200 microseconds. At 4 microsecs/bit, this works out to be 
between 4 and 7 bytes of user data delay. 


Forewarned is Forearmed. |Commodore-Amiga may make enhancements to the 
disk format in the future. Commodore-Amiga intends to provide compatibility within 
the trackdisk device. Anyone who uses these raw routines is bypassing this upward- 
compatibility and does so at her own risk. 


Trackdisk Device Errors 


The trackdisk device returns error codes whenever an operation is attempted. 


DiskIO->iotd_Req.io_Length = TRACK_SIZE; 
DiskIO->iotd Req.io Data = (APTR)Writebuffer; 
DiskIO->iotd Req.io Offset = (ULONG) (TRACK SIZE * tracknum); 
DiskIO->iotd_ Count = change_count; 
DiskIO->iotd_Req.io Command = ETD WRITE; 
if (DoIO((struct IORequest *)DiskIO) ) 
printf ("ETD_WRITE failed. Error: %1d\n",DiskI0O-iotd.io Error); 


When an error occurs, these error numbers will be returned in the io_Error field of your IOExtTD 
block. 


Trackdisk Device Error Codes 


Error Value Explanation 

TDERR_NotSpecified 20 Error could not be determined 
TDERR_NoSecHdr 21 Could not find sector header 
TDERR_BadSecPreamble 22 Error in sector preamble 

TDERR_BadSecID 23 Error in sector identifier 

TDERR_BadHdrSum 24 Header field has bad checksum 
TDERR_BadSecSum 25 Sector data field has bad checksum 
TDERR_TooFewSecs 26 Incorrect number of sectors on track 
TDERR_BadSecHdr 27 Unable to read sector header 
TDERR_WriteProt 28 Disk is write-protected 

TDERR_DiskChanged 29 Disk has been changed or is not currently present 
TDERR_SeekError 30 While verifying seek position, found seek error 
TDERR_NoMem 31 Not enough memory to do this operation 
TDERR_BadUnitNum 32 Bad unit number (unit # not attached) 
TDERR_BadDriveType 33 Bad drive type (not an Amiga 3 1/2 inch disk) 
TDERR_DriveInUse 34 Drive already in use (only one task exclusive) 
TDERR_PostReset 35 User hit reset; awaiting doom 


Trackdisk Device 317 


Example Trackdisk Program 


/* 

* Track _Copy.c 

* 

* This program does a track by track copy from one drive to another 
* 

* Compile with SAS C 5.10 LC -cfist -ms -v -L 

* 

* This program will only run from the CLI. If started from 
* the workbench, it will just exit... 

* 

* Usage: trackcopy dfx dfy 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <devices/trackdisk.h> 
#include <dos/dosextens.h> */ 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/dos_ protos.h> 


#include <stdio.h> 
#include <string.h> 


#ifdef LATTICE 


int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 
#tendif 
#define TRACK SIZE ( (LONG) (NUMSECS * TD SECTOR) ) 

/* 

* Turn the BUSY flag off/on for the drive 

* If onflag is TRUE, the disk will be marked as busy... 

* 

* This is to stop the validator from executing while 

* 


we are playing with the disks. 
* 


VOID disk _busy(UBYTE *drive, LONG onflag) 
{ 


struct StandardPacket *pk; 
struct Process *tsk; 


tsk=(struct Process *)FindTask (NULL) ; 
if (pk=AllocMem(sizeof (struct StandardPacket) ,MEMF_PUBLIC|MEMF_ CLEAR) ) 
{ 

pk->sp_Msg.mn_Node.1n_Name=(UBYTE *) & (pk->sp_ Pkt); 


pk~>sp_Pkt.dp Link=& (pk->sp_Msg); 
pk->sp_Pkt.dp Port=6(tsk->pr_ MsgPort); 
pk->sp_ Pkt 7 dp_Type=ACTION_ INHIBIT; 
pk->sp_Pkt.dp Argl=(onflag ? -1L : OL); 


PutMsg (DeviceProc(drive), (struct Message *) pk); 
WaitPort (&(tsk->pr_MsgPort)); 

GetMsg (& (tsk->pr_MsgPort)); 
FreeMem(pk, (long) sizeof (*pk) ); 


/* 
* This turns the motor off 
*/ 
VOID Motor Off(struct IOExtTD *disk) 
{ 
disk->iotd_Req.io Length=0; 
disk->iotd_Req.io Command=TD_ MOTOR; 
DoIO((struct IORequest *) disk); 


318 Amiga ROM Kernel Reference Manual: Devices 


/* 
* This turns the motor on 
*/ 


VOID Motor On(struct IOExtTD *disk) 
{ 


disk->iotd_Req.io_Length=1; 
disk->iotd_Req.io Command=TD_MOTOR; 
DoIO((struct IORequest *) disk); 


/* 
* This reads a track, reporting any errors... 
* 


SHORT Read_Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track) 
{ 
SHORT All_OK=TRUE; 


disk->iotd_Req.io Length=TRACK_SIZE; 
disk->iotd_Req.io Data=(APTR) buffer; 
disk->iotd_Req.io_Command=CMD_READ; 

disk->iotd | | Req.io . Of fset= (ULONG) (TRACK_: SIZE * track); 
DoIO((struct IORequest *)disk); 

if (disk->iotd_Req.io_Error) 

{ 


All_OK=FALSE; 
printf("Error tu when reading track %d",disk->iotd_Req.io Error, track); 


} 
return (All OK); 


/* 
* This writes a track, reporting any errors... 
*/ 


SHORT Write _Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track) 
{ 
SHORT All_OK=TRUE; 


disk->iotd_Req.io_Length=TRACK_SIZE; 

disk->iotd | | Req.io . Data=(APTR) buffer; 
disk->iotd_Req.io Command=TD_FORMAT; 
disk->iotd_Req.io Offset=(ULONG) (TRACK_SIZE * track); 
DoIO((struct IORequest *) disk); 

if (disk->iotd_Req.io_Error) 

{ 


All_OK=FALSE; 
printf("Error td when writing track %d",disk->iotd_Req.io Error,track); 


return (All_ OK); 


* This function finds the number of TRACKS on the device. 

* NOTE That this is TRACKS and not cylinders. On a Two-Head 

* drive (such as the standard 3.5" drives) the number of tracks 
* is 160, 80 cylinders, 2-heads. 

*/ 


SHORT FindNumTracks(struct IOExtTD *disk) 
disk->iotd_Req.io Command=TD_GETNUMTRACKS; 


DoIO((struct IORequest *) disk); 
return ( (SHORT) disk->iotd_ Req.io Actual); 


Trackdisk Device 319 


/* 
* This routine allocates the memory for one track and does 
* the copy loop. 

*/ 


VOID Do_Copy(struct IOExtTD *diskreq0, struct IOExtTD *diskreql) 


{ 

UBYTE *buffer; 
SHORT track; 
SHORT All _ OK; 
SHORT NumTracks; 


if (buffer=AllocMem(TRACK_SIZE,MEMF_CHIP|MEMF_ PUBLIC) ) 
{ 


printf(" Starting Motors\r"); 
Motor On (diskreq0); 
Motor On (diskreql1); 
All_OK=TRUE; 


NumTracks=FindNumTracks (diskreq0) ; 
for (track=0; (track<NumTracks) && All OK;track++) 
' printf (" Reading track %td\r",track) ; 
if (All_OK=Read_Track (diskreq0, buffer, track) ) 
printf(" Writing track %d\r",track); 


All_OK=Write_Track (diskreql, buffer, track); 


} 
if (Al1_OK) printf(" * Copy complete *"); 
printf ("\n"); 
Motor Off (diskreq0); 
Motor Off (diskreql); 
FreeMem (buffer, TRACK_SIZE) ; 
} 


else printf ("No memory for track buffer...\n"); 


Prompts the user to remove one of the disks. 

Since this program makes an EXACT copy of the disks 

AmigaDOS would get confused by them so one must be removed 
before the validator is let loose. Also, note that the 
disks may NEVER be in drives on the SAME computer at the 
SAME time unless one of the disks is renamed. This is due 
to a bug in the system. It would normally be prevented 

by a diskcopy program that knew the disk format and modified 
the creation date by one clock-tick such that the disks would 
be different. 

/ 


VOID Remove_Disks (VOID) 
{ 


+ % OF Oe OE 


printf("\nYou *MUST* remove at least one of the disks now.\n"); 
printf ("\nPress RETURN when ready\n") ; 
while (getchar()!='\n’); 


/* 
* Prompts the user to insert the disks. 
*/ 


VOID Insert _Disks(char drivel[], char drive2[]) 

{ 
printf("\nPlease insert source disk in %s\n",drivel); 
printf ("\n and destination in %s\n",drive2); 
printf ("\nPress RETURN when ready\n"); 
while (getchar()!='\n'); 


320 Amiga ROM Kernel Reference Manual: Devices 


/* 
* Open the devices and mark them as busy 
* 


VOID Do _OpenDevice(struct IOExtTD *diskreq0,struct IOExtTD *diskreql, long unit[]) 
{ 


char drivel [] 
char drive2[] 


drivel [2] 


"DFx:";  /* String for source drive */ 
"DFx:"; /* String for destination drive */ 


unit [0]+ '0’; /* Set drive number for source */ 
if (!OpenDevice(TD_NAME,unit[0], (struct IORequest *)diskreq0, OL) ) 
{ 


disk_busy (drivel, TRUE) ; 
drive2(2]) = unit[{1]+ '0’; /* Set drive number for destination */ 


if (!OpenDevice(TD_NAME,unit[1], (struct IORequest *)diskreql,0L)) 
{ 
disk_busy (drive2, TRUE) ; 


Insert _Disks (drivel, drive2) ; 
Do_Copy (diskreq0, diskreq1) ; 
Remove _Disks(); 


disk_busy (drive2, FALSE) ; 
CloseDevice((struct IORequest *)diskreql); 
} 


else printf("Could not open %s\n",drive2) ; 


disk_busy (drivel, FALSE) ; 
CloseDevice((struct IORequest *)diskreq0); 


} 
else printf ("Could not open %s\n",drivel); 


SHORT ParseArgs(int argc, char **argv, long Unit[]) 
#define OKAY 1 

{ 

int j=l, params 
char *position[] 


OKAY; 
{"First", "Second"}; 


if (arge != 3) 
{ 


printf("\nYou must specify a source and destination disk\n"); 
return (! OKAY); 


} 
else if (stremp(argv[1],argv[2]) == 0) 
{ 


printf("\nYou must specify different disks for source and destination\n"); 
return (! OKAY) ; 


else chide (params == OKAY && j<3) 
if (strnicmp(argv({j],"df",2)==0) 
me (argv(j](2] >= '0" && argv[j})(2] <= "3 && argv[(j]) [3] == ’\0’) 
Cee = argv[j])[2] - 0x30; 
gis 


printf("\n%s parameter is wrong, unit number must be 0-3\n",position[j-1]); 
params = ! OKAY; 
return (!OKAY) ; 
} 
} 


else 


printf("\nts parameter is wrong, you must specify a floppy device df0 - df3\n", 
position[j-1]); 

params=! OKAY; 

return (! OKAY) ; 

} 

j++; 

} 

return (OKAY) ; 

} 


Trackdisk Device 321 


VOID main(int argc,char **argv) 


struct IOExtTD *diskreq0; 
struct IOExtTD *diskreql; 
struct MsgPort *diskPort; 
long unit [2]; 


if (ParseArgs(argc, argv, unit)) /* Check inputs */ 
{ 
if (diskPort=CreatePort (NULL, NULL) ) 


if (diskreq0=(struct IOExtTD *)CreateExtIO(diskPort, 
sizeof (struct IOExtTD) )) 
{ 


if (diskreql=(struct IOExtTD *)CreateExtIO(diskPort, 
sizeof (struct IOExtTD))) 
{ 


Do_OpenDevice (diskreq0,diskreql, unit); 
DeleteExtIO((struct IORequest *)diskreql); 
} 
else printf ("Out of memory\n") ; 
DeleteExtIO((struct IORequest *)diskreq0); 
} 


else printf ("Out of memory\n"); 
DeletePort (diskPort) ; 


else printf ("Could not create diskReq port\n"); 


Only one per customer. Since this example program makes an exact track-for-track 
duplicate, AmigaDOS will get confused if both disks are in drives on the system at the 
same time. While the disks are inhibited, this does not cause a problem, but during normal 
operation, this will cause a system hang. To prevent this, you can relabel one of the disks. 
A commercial diskcopy program would have to understand the disk format and either 
relabel the disk or modify the volume creation date/time by a bit in order to make the disks 
look different to the system. 


Additional Information on the Trackdisk Device 


Additional programming information on the trackdisk device can be found in the include files and 
the autodocs for the trackdisk device. Both are contained in the Amiga ROM Kernel Reference 
Manual: Includes and Autodocs. 


Trackdisk Device Information 


INCLUDES devices/trackdisk.h 


devices/trackdisk.i 
AUTODOCS trackdisk.doc 





322 Amiga ROM Kernel Reference Manual: Devices 


chapter fifteen 
RESOURCES 


The Amiga’s low-level hardware control functions are collectively referred to as “Resources”. 
Most applications will never need to use the hardware at the resource level—the Amiga’s device 
interface is much more convenient and provides for multitasking. However, some high performance 
applications, such as MIDI time stamping, may require direct access to the Amiga hardware registers. 






New Features for Version 2.0 
Feature Description 


BattClock New resource 
BattMem New resource 
FileSystem New resource 











Compatibility Warning: The new features for 2.0 are not backwards compatible. 


Resources 323 


The Amiga Resources 


There are currently seven standard resources in the Amiga system. The following lists the name of 
each resource and its function. 


battclock.resource 
grants access to the battery-backed clock chip. 


battmem.resource 
grants access to non-volatile RAM. 


cia.resource 
grants access to the interrupts and timer bits of the 8520 CIA (Complex Interface Adapter) 
chips. 

disk.resource 
grants temporary exclusive access to the disk hardware. 


FileSystem.resource 
grants access to the file system. 


misc.resource 
grants exclusive access to functional blocks of chip registers. At present, definitions have been 
made for the serial and parallel hardware only. 


potgo.resource 
manages the bits of the proportional I/O pins on the game controller ports. 


The resources allow you direct access to the hardware in a way that is compatible with multitasking. 
They also allow you to temporarily bar other tasks from using the resource. You may then use the 
associated hardware directly for your special purposes. If applicable, you must return the resource 
back to the system for other tasks to use when you are finished with it. 


See the Amiga Hardware Reference Manual for detailed information on the actual hardware in- 
volved. 


Look Before You Leap. Resources are just one step above direct hardware manipulation. 
You are advised to try the higher level device and library approach before resorting to the 
hardware. 


Resource Interface 


Resources provide functions that you call to do low-level operations with the hardware they access. 
In order to use the functions of a resource, you must obtain a pointer to the resource. This is done 
by calling the OpenResource() function with the resource name as its argument. 


OpenResource() returns a pointer to the resource you request or NULL if it does not exist. 


#include <resources/filesysres.h> 
struct FileSysResource *FileSysResBase = NULL; 


if (!(FPileSysResBase = OpenResource (FSRNAME) ) ) 
printf("Cannot open %s\n",FSRNAME) ; 


324 Amiga ROM Kernel Reference Manual: Devices 


There is no CloseResource() function. When you are done with a resource, you are done with it. 
However, as you will see later in this chapter, some resources provide functions to allocate parts of 
the hardware they access. In those cases, you will have to free those parts for anyone else to use 
them. 


Each resource has at least one include file in the resources subdirectory of the include directory. 
Some of the include files contain only the name of the resource; others list structures and bit 
definitions used by the resource. The include files will be listed at the end of this chapter. 


Calling a resource function is the same as calling any other function on the Amiga. You have to 
know what parameters it accepts and the retum value, if any. The Autodocs for each resource lists 
the functions and their requirements. 


#include <hardware/cia.h> 
#include <resources/cia.h> 


struct Library *CIAResource = NULL; 


void main () 
{ 


WORD mask = 0; 


if (!(CIAResource = OpenResource (CIABNAME) ) ) 
printf ("Cannot open %s\n",CIABNAME) ; 
else 


/* What is the interrupt enable mask? */ 
mask = AbleICR(CIAResource, 0); 


printf("\nThe CIA interrupt enable mask: %x \n",mask); 


Looks Can Be Deceiving. Some resources may look like libraries and act like libraries, 
but be assured they are not libraries. 


BattClock Resource 


The battery-backed clock (BattClock) keeps Amiga time while the system is powered off. The time 
from the BattClock is loaded into the Amiga system clock as part of the boot sequence. 


The battclock resource provides access to the BattClock. Three functions allow you to read the 
BattClock value, reset it and set it to a value you desire. 


BattClock Resource Functions 


ReadBattClock() Read the time from the BattClock and returns it as the number of 
seconds since 12:00 AM, January 1, 1978. 

ResetBattClock() Reset the BattClock to 12:00 AM, January 1, 1978. 

WriteBattClock() Set the BattClock to the number of seconds you pass it relative to 
12:00 AM, January 1, 1978. 


The utility.library contains time functions which convert the number of seconds since 12:00 AM, 
January 1, 1978 to a date and time we can understand, and vice versa. You will find these functions 
useful when dealing with the BattClock. The example program below uses the Amiga2Date() utility 
function to convert the value returned by ReadBattClock(). See the “Utility Library” chapter of 


Resources 325 


the Amiga ROM Kernel Reference Manual: Libraries for a discussion of the utility.library and the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs for a listing of its functions. 


So, You Want to Be A Time Lord? This resource will allow you to set the BattClock to 
any value you desire. Keep in mind that this time will endure a reboot and could adversely 
affect your system. 


* 

. Read _BattClock.c 

* Example of reading the BattClock and converting its output to 

. a useful measure of time by calling the Amiga2Date() utility function. 
: Compile with SAS C 5.10 le -bl -cfistq -v -y -L 

eo from CLI only 


#include <exec/types.h> 

#include <dos/dos.h> 

#include <utility/date.h> 
#include <resources/battclock.h> 


#include <clib/exec_protos.h> 
#include <clib/alib protos.h> 
#include <clib/battclock protos.h> 
#include <clib/utility protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


VOID main(VOID); 


struct Library *UtilityBase = NULL; 
struct Library *BattClockBase; 


VOID main(VOID) 
{ 


UBYTE *Days[] ={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 
UBYTE *Months[] = {"January", "February", "March", "April", "May", "June", 
"July", "August", "September", "October", "November", "December"}; 
UBYTE *ampm; 
ULONG AmigaTime; 
struct ClockData MyClock; 


if (UtilityBase = (struct Library *)OpenLibrary ("utility.library", 33) ) 
{ 
if (BattClockBase= OpenResource (BATTCLOCKNAME) ) 


/* Get number of seconds till now */ 
AmigaTime = ReadBattClock(); 


/* Convert to a ClockData structure */ 
Amiga2Date (AmigaTime, &MyClock) ; 


printf("\nRobin, tell everyone the BatDate and BatTime"); 


/* Print the Date */ 

printf ("\n\nOkay Batman, the BatDate is "); 

printf ("%ts, %s td, %td",Days[MyClock.wday],Months[MyClock.month-1], 
MyClock.mday, MyClock. year) ; 


/* Convert military time to normal time and set AM/PM */ 
if (MyClock.hour < 12) 


ampm = "AM"; /* hour less than 12, must be morning */ 
else 

{ 

ampm = "PM"; /* hour greater than 12,must be night */ 

MyClock.hour -= 12; /* subtract the extra 12 of military */ 


}e 


326 Amiga ROM Kernel Reference Manual: Devices 


if (MyClock.hour == 0) 
MyClock.hour = 12; /* don’t forget the 12s */ 


/* Print the time */ 

printf ("\n the BatTime is "); 

printf ("%td:%02d:%02d %s\n\n",MyClock.hour, MyClock.min,MyClock.sec, ampm) ; 
} 


else 
printf("Error: Unable to open the %s\n",BATTCLOCKNAME) ; 


/* Close the utility library */ 
CloseLibrary (UtilityBase) ; 
} 


else 
printf("Error: Unable to open utility.library\n") ; 


Additional programming information on the battclock resource can be found in the include files and 
the Autodocs for the battclock resource and the utility library. 


BattMem Resource 


The battery-backed memory (BattMem) preserves a small portion of Amiga memory while the 
system is powered off. Some of the information stored in this memory is used during the system 
boot sequence. 


The battmem resource provides access to the BattMem. Four functions allow you to use the 
BattMem. 


BattMem Resource Functions 


ObtainBattSemaphore Obtain exclusive access to the BattMem. 

ReadBattMem() Read a bitstring from the BattMem. You specify the bit position 
and the number of bits you wish to read. 

ReleaseBattSemaphore() _ Relinquish exclusive access to the BattMem. 

WriteBattMem() Write a bitstring to the BattMem. You specify the bit position 
and the number of bits you wish to write. 


The system considers BattMem to be a set of bits rather than bytes. This is done to conserve the lim- 
ited space available. All bits are reserved, and applications should not read, or write undefined bits. 
Writing bits should be done with extreme caution since the settings will survive power-down/power- 
up. You can find the bit definitions in the BattMem include files resources/battmembitsamiga.h, 
resources/battmembitsamix.h and resources/battmembitsshared.h. They should be consulted before 
you do anything with the resource. 


You Don't Need This Resource. The BattMem resource is basically for system use 
only. There is generally no reason for applications to use it. It is documented here simply 
for completeness. 


Additional information on the battmem resource can be found in the include files and the Autodocs 
for the battmem resource. 


Resources 327 


BattMem Resource Information 


INCLUDES resources/battmem.i 
resources/battmembitsamiga.h 
resources/battmembitsamix.h 
resources/battmembitsshared.h 


AUTODOCS battmem.doc 





CIA Resource 


The CIA resource provides access to the timers and timer interrupt bits of the 8520 Complex 
Interface Adapter (CIA) A and B chips. This resource is intended for use by high performance 
timing applications such as MIDI time stamping and SMPTE time coding. 


Four functions allow you to interact with the CIA hardware. 


CIA Resource Functions 


AbleICRQ) Enable or disable Interrupt Control Register interrupts. Can also 
retum the current or previous enabled interrupt mask. 

AddICRVector() Allocate one of the CIA timers by assigning an interrupt handler to 
an interrupt bit and enabling the interrupt of one of the timers. If the 
timer you request is not available, a pointer to the interrupt structure 
that owns it will be returned. 

RemICRVector() Remove an interrupt handler from an interrupt bit and disable the 
interrupt. 

SetICRQ) Cause or clear one or more interrupts, or return the current or previ- 
ous interrupt status. 


Each CIA chip has two interval timers within it—Timer A and Timer B—that may be available. 
The CIA chips operate at different interrupt levels with the CIA-A timers at interrupt level 2 and 
the CIA-B timers at interrupt level 6. 


Choose A Timer Wisely. The timer you use should be based solely on interrupt level 
and availability. If the timer you request is not available, try for another. Whatever you 
do, do not base your decision on what you think the timer is used for by the system. 


You allocate a timer by calling AddICRVector(). This is the only way you should access a timer. If 
the function retums zero, you have successfully allocated that timer. If it is unavailable, the owner 
interrupt will be returned. 


/* allocate CIA-A Timer A */ 
inta = AddICRVector (CIAResource, CIAICRB TA, &tint); 


if (inta) /* if allocate was not successful */ 
printf("Error: Could not allocate timer\n"); 
else 


{ 
...ready for timing 
} 


328 Amiga ROM Kernel Reference Manual: Devices 


The timer is deallocated by calling RemICRVector(). This is the only way you should deallocate 
a timer. 


RemICRVector (CIAResource, CIAICRB TA, &tint); 


Your application should not make any assumptions regarding which interval timers (if any) are 
available for use; other tasks or critical operating system routines may be using the interval timers. 
In fact, in the latest version of the operating system, the timer device may dynamically allocate one 
of the interval timers. 


Time Is Of The Essence! There are a limited number of free CIA interval timers. 
Applications which use the interval timers may not be able to run at the same time if all 
interval timers are in use. As a general rule, you should use the timer device for most 
interval timing. 


You read from and write to the CIA interrupt control registers using SetICRQ and AbleICR(Q. 
SetICR() is useful for sampling which cia interrupts (if any) are active. It can also be used to 
clear and generate interrupts. AbleICR( is used to disable and enable a particular CIA interrupt. 
Additional information about these functions can be found in the Amiga ROM Kernel Reference 
Manual: Includes and Autodocs. 


Things to keep in mind: 
1. Never directly read from or write to the CIA interrupt control registers. Always use SetICR() 
and AbleICR(Q. 


2. Your interrupt routine will be called with a pointer to your data area in register Al, and a pointer 
to the code being called in register AS. No other registers are set up for you. You must observe 
the standard convention of preserving all registers except DO-D1 and AO-A1. 


3. Never tum off all level 2 or level 6 interrupts. The proper way to disable interrupts for an 
interval timer that you’ve successfully allocated is via the Able[CRQ function. 


4. Interrupt handling code should be written in assembly code and, if possible, should signal a 
task to do most of the work. 


5. Do not make assumptions about which CIA interval timers (if any) are available for use. The 
only proper way to own an interval timer is via the AddICRVector() function. 


6. Donot use SetICRQ, AbleICR(Q) and RemICRVector() to affect timers or other CIA hardware 
which your task does not own. 


Changes in the CIA resource: 


e In pre-V36 versions of the operating system, SetICR() could retum FALSE for a particular 
interrupt just prior to processing the interrupt. SetICRQ now retums TRUE for a particular 
interrupt until sometime after the interrupt has been processed. 


e Applications which only need to read a CIA interval timer should use the ReadEClock() func- 
tion of the timer device. See the “Timer Device” chapter of this manual for more information 
on ReadEClock(). 


e The timer device may dynamically allocate a free CIA interval timer. Do not make any 
assumptions regarding which interval timers are in use unless you are taking over the machine 
completely. 


Resources 329 


Cia I 


Compi 


+ 4 ot ee OE 


Run f 
/ 


#include 
#include 
#include 
#include 
#include 
#include 


#include 
#include 


#include 
#include 
#include 


/* proto 


void 
int 
int 
void 


nterval.c 


le with SAS C 5.10 le 


rom CLI only 


<exec/types.h> 
<exec/memory.h> 
<exec/tasks.h> 
<exec/interrupts.h> 
<hardware/cia.h> 
<resources/cia.h> 


<clib/exec_protos.h> 


Demonstrate allocation and use of a cia interval timer 


-bl -cfistq -v -y -L 


<clib/cia_protos.h> 
<stdlib.h> 
<stdio.h> 
<string.h> 
types */ 
StartTimer (struct freetimer *ft, struct exampledata *ed); 
FindFreeTimer (struct freetimer *ft, int preferA); 
TryTimer (struct freetimer *ft); 
main ( USHORT, char **); 


/* see usage of these defines in StartTimer() below */ 


#define 
#define 
#define 


#define 


#define 


COUNTDOWN 20 
HICOUNT OxFF 
LOCOUNT OxFF 


STOPA_AND CIACRAF_TODIN |CIACRAF_PBON | CIACRAF_OUTMODE | CIACRAF_SPMODE 


/* 


; (interval timer A on 
; STOP - 

; START bit 0 == 
; PBON bit 1 == 
; OUT bit 2 == 
; RUN bit 3 == 
’ LOAD bit 4 == 
; IN bit 5 == 
; SP bit 6 == 
7 TODIN bit 7 == 
*/ 


AND mask for use with control register A 


either CIA) 


0 (STOP IMMEDIATELY) 
same 

same 

0 (SET CONTINUOUS MODE) 
0 (NO FORCE LOAD) 

0 (COUNTS 02 PULSES) 
same 

same (unused on ciacra) 


STOPB_AND CIACRBF_ALARM | CIACRBF_PBON | CIACRBF_OUTMODE 


~ 
. 


STOP - 
START bit 
PBON bit 
OUT bit 
RUN bit 
LOAD bit 
INO bit 
IN1 bit 
ALARM bit 


Se Ne Se Ne Se Ne Se Se Se Ne Se Se Ne 
SHA PWHEH O 
re | 


* 
™~ 


AND mask for use with control register B 
{interval timer B on either CIA) 


0 (STOP IMMEDIATELY) 

same 

same 

0 (SET CONTINUOUS MODE) 

0 (NO FORCE LOAD) 

0 (COUNTS 02 PULSES) 

0 (COUNTS 02 PULSES) 

same (TOD alarm control bit) 


330 Amiga ROM Kernel Reference Manual: Devices 


#define STARTA_OR CIACRAF_START 


OR mask for use with control register A 
(interval timer A on either CIA) 


START - 
START bit 0 == 1 (START TIMER) 


All other bits unaffected. 


Ne Ne Se Me Se Se Ne Se Be te 
* 


FF 
~ 


#define STARTB OR CIACRBF_START 
/* 


OR mask for use with control register B 
(interval timer A on either CIA) 


START - 
START bit 0 == 1 (START TIMER) 


All other bits unaffected. 


Ne Se Se Se Ne Se SMe Se MeN 


* 
~ 


/* 
* Structure which will be used to hold all relevant information about 


* the cia timer we manage to allocate. 
* 


*/ 


struct freetimer 


struct Library *ciabase; /* CIA Library Base */ 
ULONG timerbit; /* timer bit allocated */ 
struct CIA *cia; /* ptr to hardware */ 
UBYTE *ciacr; /* ptr to control register */ 
UBYTE *cialo; /* ptr to low byte of timer */ 
UBYTE *ciahi; /* ptr to high byte of timer */ 
struct Interrupt timerint; /* Interrupt structure */ 
UBYTE stopmask; /* Stop/set-up timer */ 
UBYTE startmask; /* Start timer */ 


* Structure which will be used by the interrupt routine called 
* when our cia interval timer generates an interrupt. 


*/ 
struct exampledata 
struct Task *task; /* task to signal */ 


ULONG signal; /* Signal bit to use */ 
ULONG counter; 


struct CIA *ciaa 
struct CIA *ciab 


(struct CIA *) Oxbfe001; 
(struct CIA *) 0Oxbfd000; 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


/* 


Resources 331 


This is the interrupt routine which will be called when our CIA 
interval timer counts down. 


This example decrements a counter each time the interrupt routine 
is called until the counter reaches 0, at which time it signals 
our main task. 


Note that interrupt handling code should be efficient, and will 
generally be written in assembly code. Signaling another task 
such as this example does is also a useful way of handling 
interrupts in an expedient manner. 


4% OF OO 
~ 


void asm ExampleInterrupt (register _al struct exampledata *ed) 
if (ed->counter) 

ed->counter--; /* decrement counter */ 
else 

ciosuainees = COUNTDOWN; /* reset counter x7: 


Signal (ed->task, (1L << ed->signal)); 
} 


[III OI II IOI IOI IOI 


* main () 
RKTT ITOK TOK II IK I KKK KIKI IK ICICI IE / 


void main(USHORT argc,char **argv) 


struct freetimer ft; 
struct exampledata ed; 


/* Set up data which will be passed to interrupt */ 
ed.task = FindTask (OL); 
if (ed.signal = AllocSignal (-1L)) 
a Prepare freetimer structure : set-up interrupt */ 
ft.timerint.is Node.1ln Type 


ft.timerint.is Node.ln Pri 
ft.timerint.is Node.1ln_ Name 


NT_INTERRUPT; 
? 


“cia example"; 


(APTR) &ed; 
(APTR) ExampleInterrupt; 


ft.timerint.is Data 
ft.timerint.is Code 


/* Call function to find a free CIA interval timer 
area flag indicating that we prefer a CIA-A timer. 
printf ("Attempting to allocate a free timer\n") ; 
if (FindFreeTimer (&ft, TRUE) ) 
{. (ft.cia == ciaa) 
print (*Cra-A timer "); 


else 


{ 
printf ("CIA-B timer "); 
} 


if (ft.timerbit == CIAICRB TA) 
{ 
printf("A allocated\n"); 
} 

else 


{ 
printf("B allocated\n") ; 
} 


332 Amiga ROM Kernel Reference Manual: Devices 


~ 


% 0 0 OF OO 


/* We found a free interval timer. Let’s start it running. */ 
StartTimer (&ft, &ed); 

/* Wait for a signal */ 

printf ("Waiting for signal bit %ld\n",ed.signal); 

Wait (l1L<<ed.signal); 

printf ("We woke up!\n"); 

/* Release the interval timer */ 

RemICRVector (ft.ciabase,ft.timerbit, &ft.timerint) ; 


} 


else 


{ 
printf ("No CIA interval timer available\n"); 
} 


FreeSignal (ed.signal); 


} 


This routine sets up the interval timer we allocated with 
AddICRVector(). Note that we may have already received one, or 
more interrupts from our timer. Make no assumptions about the 
initial state of any of the hardware registers we will be using. 


void StartTimer(struct freetimer *ft, struct exampledata *ed) 


{ 


register struct CIA *cia; 


cia = ft->cia; 
/* Note that there are differences between control register A, 
* and B on each CIA (e.g., the TOD alarm bit, and INMODE bits. 
*/ 
if (ft->timerbit == CIAICRB_TA) 
{ 
ft->ciacr = &cia->ciacra; /* control register A x/ 
ft->cialo = &cia->ciatalo; /* low byte counter x/ 
ft->ciahi = &cia->ciatahi; /* high byte counter */ 
ft->stopmask = STOPA_AND; /* set-up mask values */ 
ft->startmask = STARTA_OR; 
} 
else 
{ 
ft->ciacr = &cia->ciacrb; /* control register B */ 
ft->cialo = &cia->ciatblo; /* low byte counter */ 
ft->ciahi = &cia->ciatbhi; /* high byte counter x/ 
ft->stopmask = STOPB_AND; /* set-up mask values */ 
ft->startmask = STARTB_OR; 
} 
/* Modify control register within Disable(). This is done to avoid 
* race conditions since our compiler may generate code such as: 
* 
* value = Read hardware byte 
* AND value with MASK 
* Write value to hardware byte 
* 
* If we take a task switch in the middle of this sequence, two tasks 
* trying to modify the same register could trash each others’ bits. 
* 


Resources 333 


* Normally this code would be written in assembly language using atomic 


* instructions so that the Disable() would not be needed. 
* 


Disable (); 


/* STOP timer, set 02 pulse count-down mode, set continuous mode */ 


*ft->ciacr &= ft->stopmask; 
Enable (); 


/* Clear signal bit - interrupt will signal us later */ 
SetSignal (0L,1L<<ed->signal) ; 


/* Count-down X # of times */ 
ed->counter = COUNTDOWN; 


/* Start the interval timer - we will start the counter after 
* writing the low, and high byte counter values 
*/ 
*ft->cialo = LOCOUNT; 
*ft->ciahi = HICOUNT; 


/* Turn on start bit - same bit for both A, and B control regs 


Disable(); 
*ft->ciacr |= ft->startmask; 


Enable (); 
} 


*/ 


/* 
* A routine to find a free interval timer. 

* 

* This routine makes no assumptions about which interval timers 

* (if any) are available for use. Currently there are two interval 
* timers per CIA chip. 

* 

* Because CIA usage may change in the future, your code should use 
* a routine like this to find a free interval timer. 

* 

* Note that the routine takes a preference flag (which is used to 

* to indicate that you would prefer an interval timer on CIA-A). 

* If the flag is FALSE, it means that you would prefer an interval 
* timer on CIA-B. 

* 

*/ 


FindFreeTimer (struct freetimer *ft, int preferA) 
{ 


struct CIABase *ciaabase, *ciabbase; 
/* get pointers to both resource bases */ 


ciaabase 
ciabbase 


OpenResource (CIAANAME) ; 
OpenResource (CIABNAME) ; 


/* try for a CIA-A timer first ? */ 
if (preferA) 


{ 
ft->ciabase 
ft->cia 

} 


else 


ciaabase; /* library address */ 
ciaa; /* hardware address */ 


{ 
ft->ciabase 
ft->cia 

} 


if (TryTimer (ft) ) 
return (TRUE); 


ciabbase; /* library address */ 
ciab; /* hardware address */ 


/* try for an interval timer on the other cia */ 


334 Amiga ROM Kernel Reference Manual: Devices 


if (!(preferA) ) 
{ 


ft->ciabase 
ft->cia 
} 


else 


ciaabase; /* library address */ 
ciaa; /* hardware address */ 


{ 
ft->ciabase ciabbase; /* library address */ 


ft->cia ciab; /* hardware address */ 
} 
if (TryTimer (ft) ) 
return (TRUE) ; 
return (FALSE) ; 
} 
/* 
* Try to obtain a free interval timer on a CIA. 
*/ 


TryTimer (struct freetimer *ft) 


if (! (AddICRVector (ft->ciabase, CIAICRB TA, &ft->timerint) )) 


{ 

ft->timerbit = CIAICRB TA; 
return (TRUE) ; 

} 


if (! (AddICRVector (ft->ciabase,CIAICRB TB, &ft->timerint) )) 


{ 

ft->timerbit = CIAICRB TB; 
return (TRUE) ; 

} 


return (FALSE); 
} 


Additional programming information on the CIA resource can be found in the include files and 
the Autodocs for the CIA resource and the 8520 spec. The includes files and Autodocs are in the 
Amiga ROM Kernel Reference Manual: Includes and Autodocs and the 8520 spec is in the Amiga 
Hardware Reference Manual. 


CIA Resource Information 


INCLUDES resources/cia.h 
resources/cia.i 
hardware/cia.h 


hardware/cia.i 
AUTODOCS cia.doc 
HARDWARE 8520 specification 





Resources 335 


Disk Resource 


The Disk resource obtains exclusive access to the floppy disk hardware There are four disk/MFM 
units available, units 0-3. 


Six functions are available for dealing with the floppy disk hardware. 


Disk Resource Functions 


AllocUnit() Allocate one of the units of the disk resource. 
FreeUnitQ() Deallocate an allocated disk unit. 
GetUnitQ) Allocate the disk for a driver. 


GetUnitIDQ) Retum the drive ID of a specified drive unit. 
GiveUnit0 Free the disk. 
ReadUnitIDQ _ Reread and retum the drive ID of a specified unit. 


The disk resource provides both a gross and a fine unit allocation scheme. AllocUnit() and 
FreeUnit( are used to claim a unit for long term use, and GetUnit() and GiveUnit() are used to 
claim a unit and the disk hardware for shorter periods. 


The trackdisk device uses and abides by both allocation schemes. Because a trackdisk unit is never 
closed for Amiga 3.5" drives (the file system keeps them open) the associated resource units will 
always be allocated for these drives. GetUnit() and GiveUnit() can still be used, however, by other 
applications that have not succeeded with AllocUnit(). 


You must not change the state of of a disk that the trackdisk device is using unless you either 
a) force its removal before giving it up, or 
b) retum it to the original track (with no changes to the track), or 
c) CMD_STOP the unit before GetUnit(), update the current track number and CMD_START it 
after GiveUnit(). This option is only available under V36 and higher versions of the operating 
system. 


ReadUnitIDQ) is provided to handle drives which use the unit number in a dynamic manner. 
Subsequent GetUnit() calls will returm the value obtained by ReadUnitIDQ. 


It is therefore possible to prevent the trackdisk device from using units that have not yet been 
mounted by successfully performing an AllocUnit() for that unit. It is also possible to starve 
trackdisk usage by performing a GetUnit(). The appropriate companion routine (FreeUnit() or 
GiveUnit()) should be called to restore the resource at the end of its use. 
/ * 

fi Get_Disk_Unit_ID.c 
Example of getting the UnitID of a disk 


* 
x 
* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 
* 

* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <dos/dos.h> 
#include <resources/disk.h> 
#include <clib/exec_protos.h> 


#include <stdio.h> 


336 Amiga ROM Kernel Reference Manual: Devices 


#ifdef LATTICE 
int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 


/* There is no amiga.lib stub for this function so a pragma is required 
* This is a pragma for SAS C 

* Your compiler may require a different format 

* 

#pragma libcall DiskBase GetUnitID le 1 

#tendif 


struct Library *DiskBase = NULL; 
LONG GetUnitID (long); 
void main(int argc, char **argv) 


{ 
LONG ids= 0; 
LONG type; 


if (!(DiskBase= (struct Library *)OpenResource (DISKNAME) ) ) 
printf ("Cannot open %s\n,DISKNAME") ; 
else 
{ 
printf ("Defined drive types are:\n"); 
printf(" AMIGA $00000000\n"); 
printf(" 5.25’" $55555555\n"); 
printf(" AMIGA $00000000 (high density) \n"); 
printf(" None SPFFFFFFF\n\n"); 


/* What are the UnitIDs? */ 
for (ids = 0; ids < 4; ids++) 
{ 


type = GetUnitID (ids); 
printf("The UnitID for unit %d is $%081x\n",ids, type); 


Additional programming information on the disk resource can be found in the include files and the 
Autodocs for the disk resource. 


Disk Resource Information 


INCLUDES resources/disk.h 


resources/disk.i 
AUTODOCS disk.doc 





FileSystem Resource 


The FileSystem resource retums the filesystems that are available on the Amiga. It has no func- 
tions. Opening the FileSystem resource returns a pointer to a List structure containing the current 
filesystems in the Amiga. 


/ 
Get_Filesys.c 


Example of examining the FileSysRes list 


% eH 


Compile with SAS C 5.10 lec -bl -cfistq -v -y -L 


Resources 337 


*/ 


#include <exec/types.h> 

#include <exec/memory.h> 

#include <dos/dos.h> 

#include <resources/filesysres.h> 


#include <clib/exec_protos.h> 
#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 
int chkabort (void) { return(0); } /* really */ 

#fendif 


struct FileSysResource *FileSysResBase = NULL; 


void main(int argc, char **argv) 


struct FileSysEntry *fse; 

int x; 

/* NOTE - you should actually be in a Forbid while accessing any 

* system list for which no other method of arbitration is available. 

* However, for this example we will be printing the information 

* (which would break a Forbid anyway) so we won’t Forbid. 

* In real life, you should Forbid, copy the information you need, 

* Permit, then print the info. 

*/ 

if (!(FileSysResBase = (struct FileSysResource *)OpenResource (FSRNAME) ) ) 
printf ("Cannot open %s\n",FSRNAME) ; 

else 


{ 

for ( fse = (struct FileSysEntry *)FileSysResBase->fsr_ FileSysEntries.1lh_ Head; 
fse->fse_Node.1ln_Succ; 
fse = (struct FileSysEntry *) fse->fse_Node.1ln_Succ) 


printf ("Found filesystem creator: %s\n", fse->fse_Node.1n_Name) ; 
printf (" DosType: "); 
for (x=24; x>=8; x-=8) 

putchar((fse->fse_DosType >> x) & OxFF); 
putchar((fse->fse_DosType & OxFF) + 0x30); 


printf ("\n Version: %d", (fse->fse_ Version >> 16)); 
printf (".%ld\n\n", (fse->fse_Version & OxFFFF)); 
} 


Additional programming information on the FileSystem resource can be found in the include 
files and the Autodocs for the FileSystem resource in the Amiga ROM Kernel Reference Manual: 
Includes and Autodocs and the “Expansion ” chapter of the Amiga ROM Kernel Reference Manual: 
Libraries. 


FileSystem Resource Information 


INCLUDES resources/filesysres.h 
resources/filesysres.i 


AUTODOCS filesysres.doc 
LIBRARIES expansion library 





338 Amiga ROM Kernel Reference Manual: Devices 


Misc Resource 


The misc resource oversees usage of the serial data port, the serial communication bits, the parallel 
data and handshake port, and the parallel communication bits. Before using serial or parallel port 
hardware, it first must be acquired from the misc resource. 


The misc resource provides two functions for allocating and freeing the serial and parallel hardware. 


Misc Resource Functions 


AllocMiscResource() Allocate one of the serial or parallel misc resources. 
FreeMiscResource() Deallocate one of the serial or parallel misc resources. 


Once you’ve successfully allocated one of the misc resources, you are free to write directly to its 
hardware locations. Information on the serial and parallel hardware can be found in the Amiga 
Hardware Reference Manual and the hardware/custom.h include file. 


The two examples below are assembly and C versions of the same code for locking the serial misc 
resources and waiting for CTRL-C to be pressed before releasing them. 


ASSEMBLY EXAMPLE OF ALLOCATING MISC RESOURCES 


Alloc Misc.a 


Assembly language fragment that grabs the two parts of the serial 
resource (using misc.resource). If it gets the resource, it will 
wait for CTRL-C to be pressed before releasing. 


While we are waiting, the query serial program should be run. It will try 
to open the serial device and if unsuccessful, will return the name of the 
owner. It will be us, Serial Port Hog! 


When a task has successfully obtained the serial resource, it "owns" 
the hardware registers that control the serial port. No other tasks 
are allowed to interfere. 


Assemble with Adapt 
HX68 Allocate _Misc.a to Allocate _Misc.o 


Link 
Blink FROM Allocate Misc.o TO Allocate Misc LIB LIB:amiga.lib 


0b oF 0b 0 OE OF OF OF OF OF OF OF OF OF OE 


INCDIR "“include:" 

INCLUDE "exec/types.i" 
INCLUDE "resources/misc.i" 
INCLUDE "dos/dos.i" 


xref _AbsExecBase ; We get this from outside... 
xref LVOOpenResource ; We get this from outside... 
, 


xref “LvOWait ; We get this from outside... 


Open Exec and the misc.resource, check for success 


Ne Ne Ne 


move.l _AbsExecBase, a6 ;Prepare to use exec 
lea.l MiscName (pc) ,al 

jsr _LVOOpenResource (a6) 7;Open "misc.resource" 
move.l d0,da7 ;Stash resource base 


bne.s resource ok 
moveq #RETURN_FAIL,d0 
rts 


resource _ok exg.1 a7,a6 ;Put resource base in A6 


Resources 339 


We now have a pointer to a resource. 
Call one of the resource’s library-like vectors. 


Se Se Se se 


move.] #MR_SERIALBITS,d0 ;We want these bits 
lea.1l MyName (pc) ,al ;This is our name 

jsr MR_ALLOCMISCRESOURCE (a6) 

tst.l do 

bne.s no bits ;Someone else has it... 


move.l #MR_SERIALPORT,d0 
lea.l MyName (pc) ,al 


jsr MR_ALLOCMISCRESOURCE (a6) 
tst.l dao 
bne.s no_port ;Someone else has it... 


We just stole the serial port registers; wait. 
Nobody else can use the serial port, including the serial.device! 


Ne Se Se se 


exg.1 a7,a6 yuse exec again 

move.l1 #SIGBREAKF CTRL _C,d0 

jsr LVOWait (a6) ;Wait for CTRL-C | 
exg.1l d7,a6 ;Get resource base back 


Free ‘em up 


Ne Se Ne 


move.] #MR_SERIALPORT,d0 


jsr MR_FREEMISCRESOURCE (a6) 
no_port 
move.1 #MR_SERIALBITS, d0 
jsr MR_FREEMISCRESOURCE (a6) 
no_bits 
moveq #RETURN_ FAIL, dO 
rts 
; 
7 Text area 
vv 
MiscName dc.b 'misc.resource’ ,0 
MyName dc.b ‘Serial Port Hog’,0 
dc.w 0 
END 


C EXAMPLE OF ALLOCATING MISC RESOURCES 


Allocate _Misc.c 


Example of allocating a miscellaneous resource 

We will allocate the serial resource and wait till 
CTRL-C is pressed. While we are waiting, the 
query serial program should be run. It will try 
to open the serial device and if unsuccessful, will 
return the name of the owner. It will be us! 


Compile with SAS C 5.10 lc -bl -cfistq -v -y -L 


Run from CLI only 
/ 


M0 OF OF OF 0b Ok OF Fb OF OO 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <dos/dos.h> 
#include <resources/misc.h> 


#include <clib/exec_protos.h> 
#include <clib/misc_protos.h> 


#include <stdio.h> 
#ifdef LATTICE 
int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ 


int chkabort (void) { return(0); } /* really */ 
#fendif 


340 Amiga ROM Kernel Reference Manual: Devices 


struct Library *MiscBase = NULL; 

void main(int argc, char **argv) 

UBYTE *owner = NULL; /* owner of misc resource */ 

if (!(MiscBase= (struct Library *)OpenResource (MISCNAME) ) ) 
printf ("Cannot open %s\n",MISCNAMBE) ; 


else 


/* Allocate both pieces of the serial hardware */ 


if ((owner = AllocMiscResource (MR_SERIALPORT,"Serial Port Hog")) == NULL) 
{ 


if ((owner = AllocMiscResource (MR_SERIALBITS,"Serial Port Hog")) == NULL) 
{ 


/* Wait for CTRL-C to be pressed */ 
printf ("\nWaiting for CTRL-C...\n"); 
Wait (SIGBREAKF_CTRL C); 


/* We're back */ 


/* Deallocate the serial port register */ 
FreeMiscResource (MR_SERIALBITS) ; 
} 


else 


printf("\nUnable to allocate MR_SERIALBITS because %s owns it\n",owner); 


/* Deallocate the serial port */ 
FreeMiscResource (MR_SERIALPORT) ; 


else 


printf("\nUnable to allocate MR_SERIALPORT because %s owns it\n",owner); 


The example below will try to open the serial device and execute the SDCMD_QUERY command. 
If it cannot open the serial device, it will do an AllocMiscResource() on the serial port and retum 


the name of the owner. 


/* 
* Query Serial.c 

* 

* We will try to open the serial device and if unsuccessful, 
* will return the name of the owner. 

* 

* Compile with SAS C 5.10 le -bl -cfistq -v -y -L 

* 

* Run from CLI only 

*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <dos/dos.h> 
#include <resources/misc.h> 
#include <devices/serial.h> 


#include <clib/exec_protos.h> 
#include <clib/alib_ protos.h> 
#include <clib/dos protos.h> 

#include <clib/misc_protos.h> 


#include <stdio.h> 
#include <stdlib.h> 


#ifdef LATTICE 

int CXBRK(void) { return(0); } 

int chkabort (void) { return(0); } /* really */ 
#fendif 


struct Library *MiscBase; 


struct MsgPort *SerialMP; /* Message port pointer */ 
struct IOExtSer *SerialI0O; /* I/O request pointer */ 


/* Disable SAS CTRL/C handling */ 


Resources 341 


void main(void) 


UWORD status; /* return value of SDCMD_QUERY */ 
UBYTE *user; /* name of serial port owner if not us */ 


if (SerialMP=CreatePort (NULL,NULL) ) 


i (SerialIO=(struct IOExtSer *)CreateExtIO(SerialMP, sizeof(struct IOExtSer)) ) 
- (OpenDevice (SERIALNAME, OL, (struct IORequest *)SerialIO,0)) 
a aeeGNNis did not open", SERIALNAME) ; 
MiscBase= (struct Library *)OpenResource (MISCNAME) ; 


/* Find out who has the serial device */ 
if ((user = AllocMiscResource (MR_SERIALPORT,"Us")) == NULL) 
{ 


printf ("\n"); 
FreeMiscResource (MR_SERIALPORT) ; 
} 
else 
printf(" because %s owns it \n\n",user); 
} 
else 


{ 
SerialIO->10Ser.io_Command = SDCMD_QUERY; 
DoIO((struct IORequest *)SerialI0O); /* execute query */ 


status = SerialIO->io Status; /* store returned status */ 
printf("\tThe serial port status is %x\n",status); 


CloseDevice((struct IORequest *)SeriallI0O); 
} 


DeleteExtIO(Seriall0O); 
} 


else 
printf ("Can’t create I/O request\n"); 


DeletePort (SerialMP) ; 
} 


else 


printf("Can’t create message port\n"); 


Take Over Everything. There are two serial.device resources to take over, 
MR_SERIALBITS and MR_SERIALPORT. You should get both resources when you 
take over the serial port to prevent other tasks from using them. The parallel.device also 
has two resources to take over. See the resources/misc.h include file for the relevant 
definitions and structures. 


Under V1.3 and earlier versions of the Amiga system software the MR-GETMISCRESOURCE 
routine will always fail if the serial device has been used at all by another task (even if that task 
has finished using the resource. In other words, once a printer driver or communication package 
has been activated, it will keep the associated resource locked up preventing your task from using 
it. Under these conditions, you must get the resource back from the system yourself. 


You do this by calling the function FlushDevice(Q): 


/ 


% 0 0 oF OF tO 


A safe way to expunge ONLY a certain device. The serial.device holds 
on to the misc serial resource until a general expunge occurs. 

This code attempts to flush ONLY the named device out of memory and 
nothing else. If it fails, no status is returned since it would have 
no valid use after the Permit (). 


342 Amiga ROM Kernel Reference Manual: Devices 


#include <exec/types.h> 
#include <exec/execbase.h> 


#include <clib/exec_protos.h> 
void FlushDevice(char *); 

extern struct ExecBase *SysBase; 
void FlushDevice(char *name) 
Whee Device *devpoint; 


Forbid(); 


if (devpoint=(struct Device *)FindName (&SysBase->DeviceList,name) ) 
RemDevice (devpoint) ; 


Permit (); 
} 


Additional programming information on the misc resource can be found in the include files and the 
Autodocs for the misc resource. 


Misc Resource Information 


INCLUDES resources/misc.h 
resources/misc.i 


hardware/custom.h 
hardware/custom.i 


AUTODOCS misc.doc 





Potgo Resource 


The potgo resource is used to get control of the hardware POTGO register connected to the 
proportional I/O pins on the game controller ports. There are two registers, POTGO (write-only) 
and POTINP (read-only). These pins could also be used for digital I/O. 


The potgo resource provides three functions for working with the POTGO hardware. 


Potgo Resource Functions 


AllocPotBits() Allocate bits in the POTGO register. 

FreePotBits() Free previously allocated bits in the POTGO register. 

WritePotgo() Set and clear bits in the POTGO register. The bits must have been 
allocated before calling this function. 


The example program shown below demonstrates how to use the ptogo resource to track mouse 
button presses on port 1. 


/ 
Read_Potinp.c 


An example of using the potgo.resource to read pins 9 and 5 of 

port 1 (the non-mouse port). This bypasses the gameport.device. 

When the right or middle button on a mouse plugged into port 1 is pressed, 
the read value will change. 


% 0 OE 


Resources 343 


* 
* Use of port 0 (mouse) is unaffected. 


+ 


Compile with SAS C 5.10 le -bl -cfistq -v -y -L 


+ 


Run from CLI only 
*/ 


#include <exec/types.h> 
#include <exec/memory.h> 
#include <dos/dos.h> 
#include <resources/potgo.h> 
#include <hardware/custom.h> 


#include <clib/exec_protos.h> 
#include <clib/potgo protos.h> 


#include <stdio.h> 


#ifdef LATTICE 

int CXBRK(void) {return(0);} /* Disable SAS Ctrl-C checking */ 
int chkabort (void) { return(0); } /* really */ 

#endif 


struct PotgoBase *PotgoBase; 
ULONG potbits; 
UWORD value; 


#define UNLESS (x) if(! (x)) 
#define UNTIL(x) while(! (x)) 


#define OUTRY 1L<<15 
#define DATRY 1L<<14 
#define OUTRX 1L<<13 
#define DATRX 1L<<12 


extern struct Custom far custom; 
void main(int argc,char **argv) 


UNLESS (PotgoBase=(struct PotgoBase *)OpenResource("potgo. resource") ) 
return; 


potbits=AllocPotBits (OUTRY | DATRY | OUTRX | DATRX) ; 
/* Get the bits for the right and middle mouse buttons on the alternate mouse port. */ 


if (potbits != (OUTRY|DATRY|OUTRX|DATRX) ) 


{ 

printf("Pot bits are already allocated! %1x\n",potbits) ; 
FreePotBits (potbits) ; 

return; 


} 


/* Set all ones in the register (masked by potbits) */ 
WritePotgo (OxFFFFFFFFL, potbits) ; 


printf("\nPlug a mouse into the second port. This program will indicate when\n"); 
printf("the right or middle button (if the mouse is so equipped) is pressed.\n"); 
printf ("Stop the program with Control-C. Press return now to begin.\n"); 


getchar (); 
UNTIL (SIGBREAKF_CTRL_C & SetSignal (OL, OL)) 
/* until CTRL-C is pressed */ 
{ 
/* Read word at $DFF016 */ 
value = custom.potinp; 


/* Show what was read (restricted to our allocated bits) */ 
printf ("POTINP = $%lx\n",value & potbits); 
} 


FreePotBits(potbits) ; 
} 


344 Amiga ROM Kernel Reference Manual: Devices 


Additional programming information on the potgo resource can be found in the include files and 
the Autodocs for the potgo resource. 


Potgo Resource Information 


INCLUDES resources/potgo.h 
resources/potgo.i 


utility/hooks.h 
utility/hooks.i 


AUTODOCS potgo.doc 





Resources 345 





appendix A 
IFF: INTERCHANGE FILE 
FORMAT 


One of the Amiga’s strengths is the wide acceptance of several IFF specifications. Most notable 
is the ease with which graphic files (of form “ILBM”) can be transferred among dozens of paint, 
animation and special effects packages. This ability to to easily share data between a variety of 
programs lets the user select the best program for a specific job rather than fighting the restritions 
of a single, all-in-one software package. Developers can market specialized applications that are 
good at a certain limited set of operations, and with the help of the multitasking Amiga operating 
system, create the effect of a large integrated system. 


Any developer with a package that creates or reads data should use an existing IFF standard. If 
no current IFF form is suitable then the developer should contact other developers and users with 
similar needs and work out a new IFF form using the design principles specified in this appendix. 
To prevent conflicts, new IFF forms must be registered with Commodore before they are used. No 
additional restrictions are placed on the design of IFF forms aside from the general IFF syntax rules 
listed here. 


IFF: Interchange File Format 347 


Contents of the IFF Specification 


EA IFF 85 - General IFF Format Specifications 
Quick Introduction to IFF ..........0. cece cence net e ence eee n ence teen en enes 


FORM Specifications from the Original EA Document 

IL BM = Interleaved Bitmap iii 2 cctv cue deed abck beaees aude anades euviewea came ge tues 
FEXT =: Formatted Text 133009325. chess doles ois hs aoe nde Pas eed naa ee Romer eae 
SMUS = Simple: Musical Score sss<42j tsetse cipcs acne vice eewdauns gidisie Meudwene ule as 
SSV.X = 8-bit Sampled VOICE a¢ seiiv sashes bp daiaaey ens ioevAebansadiaventn ee oes vas 


Third Party Public FORM and Chunk Specifications and Additional Documents 

IFF-FORM and ‘Chunk Registry. 2..5..4.03490 34 eee oars oe Weed evegeas Ainkie euros et 
Third Party Public FORM and Chunk Specifications .............. 0... cee eee cece eee eee 
Additional Documents :....eraijcciensowet sia desea ese bee acuwesdes ae dee eeitawes ts cies 


IFF Source Code 
BEE Include Piles ea. 20 anvorsi capi ahds evar tek aes recto ended pean ahead Ce 
Source listings Of Cxamples 30n sash ede baweueves terenid ied ae Seabees enahes aruda Beoekes 


348 Amiga ROM Kernel Reference Manual: Devices 


A Quick Introduction to IFF 


Jerry Morrison, Electronic Arts 
10-17-88 


IFF is the Amiga-standard "Interchange File Format", designed to work across many machines. 


Why IFF? 
Did you ever have this happen to your picture file? 


You can’t load it into another paint program. 

You need a converter to adopt to "ZooPaint" release 2.0 or a new hardware feature. 
You must "export" and "import" to use it in a page layout program. 

You can’t move it to another brand of computer. 


What about interchanging musical scores, digitized audio, and other data? It seems the only thing 
that does interchange well is plain ASCII text files. 


It’s inexcusable. And yet this is "normal" in MS-DOS. 


What is IFF? 


IFF, the "Interchange File Format" standard, encourages multimedia interchange between different 
programs and different computers. It supports long-lived, extensible data. It’s great for composite 
files like a page layout file that includes photos, an animation file that includes music, and a library 
of sound effects. 


IFF is a 2-level standard. The first layer is the "wrapper" or “envelope” structure for all IFF files. 
Technically, it’s the syntax. The second layer defines particular IFF file types such as ILBM (stan- 
dard raster pictures), ANIM (animation), SMUS (simple musical score), and 8SVX (8-bit sampled 
audio voice). 


IFF is also a design idea: 
programs should use interchange formats for their everyday storage. 


This way, users rarely need converters and import/export commands to change software releases, 
application programs, or hardware. 


What’s the trick? 


File compatibility is easy to achieve if programmers let go of one notion—dumping internal data 
structures to disk. A program’s intemal data structures should really be suited to what the program 
does and how it works. What’s "best" changes as the program evolves new functions and methods. 
But a disk format should be suited to storage and interchange. 


Once we design internal formats and disk formats for their own separate purposes, the rest is easy. 
Reading and writing become behind-the-scenes conversions. But two conversions hidden in each 
program is much better than a pile of conversion programs. 


Does this seem strange? It’s what ASCII text programs do! Text editors use line tables, piece tables, 
gaps, and other structures for fast editing and searching. Text generators and consumers construct 
and parse files. That’s why the ASCII standard works so well. 


IFF Specification 349 





Also, every file must be self-sufficient. E.g., a picture file has to include its size and number of 
bits/pixel. 


What does an IFF file look like? 
IFF is based on data blocks called "chunks". Here’s an example color map chunk: 


0, O, O, 255, 
255, 255 ... 






char typelD[4] 
unsigned long dataSize 
char data ] 


in an ILBM file, CMAP means "color map" 
48 data bytes 
16 3-byte color values: black, white,.... 






A chunk is made of a 4-character type identifier, a 32 bit data byte count, and the data bytes. It’s 
like a Macintosh "resource" with a 32-bit size. 


Fine points: 
e Every 16- and 32-bit number is stored in 68000 byte order—highest byte first. 


e An Intel CPU must reverse the 2- or 4-byte sequence of each number. This applies to chunk 
dataSize fields and to numbers inside chunk data. It does not affect character strings and byte 
data because you can’t reverse a 1-byte sequence. But it does affect the 32-bit math used in 
IFF’s MakeID macro. The standard does allow CPU specific byte ordering hidden within a 
chunk itself, but the practice is discouraged. 


e Every 16- and 32-bit number is stored on an even address. 


e Every odd-length chunk must be followed by a 0 pad byte. This pad byte is not counted in 
dataSize. 


e An ID is made of 4 ASCII characters in the range " " (space, hex 20) through "™" (tilde, hex 
TE). Leading spaces are not permitted. 


e IDs are compared using a quick 32-bit equality test. Case matters. 


A chunk typically holds a C structure, Pascal record, or an array. For example, an ’ILBM’ picture 
has a ’BMHD?’ bitmap header chunk (a structure) and a BODY’ raster body chunk (an array). 


To construct an IFF file, just put a file type ID (like "ILBM’) into a wrapper chunk called a FORM’ 
(Think "FILE"). Inside that wrapper place chunks one after another (with pad bytes as needed). The 
chunk size always tells you how many more bytes you need to skip over to get to the next chunk. 


350 Amiga ROM Kernel Reference Manual: Devices 





FORM is a special chunk ID 
24070 data bytes 
FORM type is ILBM 


fp spwpe a BMHD bitmap header chunk 


(20 data bytes) 


a CMAP color map chunk 








0, 0, 0, 255 


0 a pad byte 


a BODY raster body chunk 
ete ||| 





A FORM always contains one 4-character FORM type ID (a file type, in this case "ILBM’) 
followed by any number of data chunks. In this example, the FORM type is ’ILBM’, which stands 
for InterLeaved Bitmap. (ILBM is an IFF standard for bitplane raster pictures.) This example has 
3 chunks. Note the pad byte after the odd length chunk. 


Within FORMs ILBM, ’BMHD’ identifies a bitmap header chunk, ’CMAP’ a color map, and 
*BODY’ a raster body. In general, the chunk IDs in a FORM are local to the FORM type ID. 
The exceptions are the 4 global chunk IDs FORM’, ’LIST’, CAT ’, and PROP’. (A FORM may 
contain other FORM chunks. E.g., an animation FORM might contain picture FORMs and sound 
FORMS.) 


How to read an IFF file? 


Example code and modules are provided for reading IFF files using iffparse.library. However, if 
you wish to read a non-complex FORM by hand, the following logic can be used. 


Once you have entered the FORM (for example, the FORM ILBM shown above), stored the FORM 
length (24070 in the ILBM example) and are positioned on the first chunk, you may: 


Loop: (until end-of-file or end-of-form) 


- Read the 4-character identifier of the chunk 
- Read the 32-bit (4 byte) chunklength 
- Decide if you want that chunk 
If yes, read chunklength bytes into destination structure 
or buffer 
If no, seek forward chunklength bytes 
- If chunklength is odd, seek one more byte 


IFF Specification 351 


Every IFF file is a FORM’, LIST’, or °CAT ’ chunk. You can recognize an IFF file by those first 
4 bytes. ("FORM is far and away the most common. We’ll get to LIST and CAT below.) If the file 
contains a FORM, dispatch on the FORM type ID to a chunk-reader loop like the one above. 


File extensibility 


IFF files are extensible and forward/backward compatible: 


e Chunk contents should be designed for compatibility across and for longevity. Every chunk 
should have a path for expansion; at minimum this will be an unused bit or two. 


e The standards team for a FORM type can extend one of the chunks that contains a structure by 


appending new, optional structure fields. 


e Anyone can define new FORM types as well as new chunk types within a FORM type. Storing 
private chunks within a FORM is OK, but be sure to register your activities with Commodore 


Applications and Technical Support. 


e Achunk can be superseded by a new chunk type, e.g., to store more bits per RGB color register. 
New programs can output the old chunk (for backward compatibility) along with the new 


chunk. 


e If you must change data in an incompatible way, change the chunk ID or the FORM type ID. 


Advanced Topics: CAT, LIST, and PROP (not all that important) 


Sometimes you want to put several "files" into one, such as a picture library. This is what CAT is 


for. It "concatenates" FORM and LIST chunks. 


24070 
‘ILBM’ 


24070 





concatenation 

48160 data bytes 

hint: contains FORMs ILBMs 
A FORM ILBM 


Another FORM ILBM 


352 Amiga ROM Kernel Reference Manual: Devices 


This example CAT holds two ILBMs. It can be shown outline-style: 


CAT ILBM 
--FORM ILBM 
- ++ -BMHD 
+++ CMAP 
-+--BODY 
--FORM ILBM 
-+..BMHD 
+ +.CMAP 
«+.BODY 


a complete FORM ILBM picture 


“NCC 


Sometimes you want to share the same color map across many pictures. LIST and PROP do this: 


LIST ILBM 

--PROP ILBM default properties for FORMs ILBM 

«CMAP an ILBM CMAP chunk (there could be a BMHD chunk here, too) 
--FORM ILBM 

--..BMHD (there could be a CMAP here to override the default) 
-.--BODY 

.-FORM ILBM 

-.».»BMHD (there could be a CMAP here to override the default) 
.-..-BODY 


A LIST holds PROPs and FORMs (and occasionally LISTs and CATs). A PROP ILBM contains 
default data (in the above example, just one CMAP chunk) for all FORMs ILBM in the LIST. Any 
FORM may override the PROP-defined default with its own CMAP. All PROPs must appear at 
the beginning of a LIST. Each FORM type defines as standard (among other things) which of its 
chunks are "property chunks" (may appear in PROPs) and which are "data chunks” (may not appear 
in PROPs). 


IFF Specification 353 


“EA IFFE 85" Standard for Interchange Format Files 


Document Date: January 14, 1985 (Updated Oct, 1988 Commodore-Amiga, Inc.) 
From: Jerry Morrison, Electronic Arts 
Status Of Standard: _ Released to the public domain, and in use 


1. Introduction 
Standards are Good for Software Developers 


As home computer hardware evolves into better and better media machines, the demand increases 
for higher quality, more detailed data. Data development gets more expensive, requires more 
expertise and better tools, and has to be shared across projects. Think about several ports of a 
product on one CD-ROM with SOOM Bytes of common data! 


Development tools need standard interchange file formats. Imagine scanning in images of "player" 
shapes, transferring them to an image enhancement package, moving them to a paint program for 
touch up, then incorporating them into a game. Or writing a theme song with a Macintosh score 
editor and incorporating it into an Amiga game. The data must at times be transformed, clipped, 
filled out, and moved across machine kinds. Media projects will depend on data transfer from 
graphic, music, sound effect, animation, and script tools. 


Standards are Good for Software Users 


Customers should be able to move their own data between independently developed software 
products. And they should be able to buy data libraries usable across many such products. The 
types of data objects to exchange are open-ended and include plain and formatted text, raster and 
structured graphics, fonts, music, sound effects, musical instrument descriptions, and animation. 


The problem with expedient file formats—typically memory dumps is that they’re too provincial. 
By designing data for one particular use (such as a screen snapshot), they preclude future expansion 
(would you like a full page picture? a multi-page document?). In neglecting the possibility that 
other programs might read their data, they fail to save contextual information (how many bit planes? 
what resolution?). Ignoring that other programs might create such files, they’re intolerant of extra 
data (a different picture editor may want to save a texture palette with the image), missing data (such 
as no color map), or minor variations (perhaps a smaller image). In practice, a filed representation 
should rarely mirror an in-memory representation. The former should be designed for longevity; 
the latter to optimize the manipulations of a particular program. The same filed data will be read 
into different memory formats by different programs. 


The IFF philosophy: "A little behind-the-scenes conversion when programs read and write files is 
far better than NxM explicit conversion utilities for highly specialized formats". 


So we need some standardization for data interchange among development tools and products. The 
more developers that adopt a standard, the better for all of us and our customers. 


Here is "EA IFF 1985" 


Here is our offering: Electronic Arts’ IFF standard for Interchange File Format. The full name 
is "EA IFF 1985". Altematives and justifications are included for certain choices. Public domain 
subroutine packages and utility programs are available to make it easy to write and use IFF- 
compatible programs. 


IFF Specification 355 


Part 1 introduces the standard. Part 2 presents its requirements and background. Parts 3, 4, and 5 
define the primitive data types, FORMs, and LISTs, respectively, and how to define new high level 
types. Part 6 specifies the top level file structure. Section 7 lists names of the group responsible for 
this standard. Appendix A is included for quick reference and Appendix B. 


References 


1979 for an 8-bit character set. See also ISO standard 2022 and ISO/DIS standard 6429.2. 


The C Programming Language, Brian W. Kemighan and Dennis M. Ritchie, Bell Laboratories. 
Prentice-Hall, Englewood Cliffs, NJ, 1978. 


C, A Reference Manual, Samuel P. Harbison and Guy L. Steele Jr., Tartan Laboratories. Prentice- 
Hall, Englewood Cliffs, NJ, 1984. 


Compiler Construction, An Advanced Course, edited by F. L. Bauer and J. Eickel (Springer-Verlag, 
1976). This book is one of many sources for information on recursive descent parsing. 





DIF Technical Specification © 1981 by Software Arts, Inc. DIF™ is the format for spreadsheet 
data interchange developed by Software Arts, Inc. DIF™ is a trademark of Software Arts, Inc. 


"FTXT" IFF Formatted Text, from Electronic Arts. IFF supplement document for a text format. 


"ILBM" IFF Interleaved Bitmap, from Electronic Arts. IFF supplement document for a raster image 
format. 


M68000 16/32-Bit Microprocessor Programmer’s Reference Manual © 1984, 1982, 1980, 1979 by 
Motorola, Inc. 





PostScript Language Manual © 1984 Adobe Systems Incorporated. 
PostScript™ is a trademark of Adobe Systems, Inc. 
Times and Helvetica® are registered trademarks of Allied Corporation. 


Inside Macintosh © 1982, 1983, 1984, 1985 Apple Computer, Inc., a programmer’s reference 
manual. 

Apple® is a trademark of Apple Computer, Inc. 

MacPaint™ is a trademark of Apple Computer, Inc. 

Macintosh™ is a trademark licensed to Apple Computer, Inc. 


Corporation. Introduction to InterScript © 1985 Xerox Corporation. 





Amiga® is a registered trademark of Commodore-Amiga, Inc. 


Electronics Arts™ is a trademark of Electronic Arts. 


356 Amiga ROM Kernel Reference Manual: Devices 


2. Background for Designers 


Part 2 is about the background, requirements, and goals for the standard. It’s geared for people who 
want to design new types of IFF objects. People just interested in using the standard may wish to 
quickly scan this section. 


What Do We Need? 


A standard should be long on prescription and short on overhead. It should give lots of rules for 
designing programs and data files for synergy. But neither the programs nor the files should cost 
too much more than the expedient variety. Although we are looking to a future with CD-ROMs and 
perpendicular recording, the standard must work well on floppy disks. 


For program portability, simplicity, and efficiency, formats should be designed with more than one 
implementation style in mind. It ought to be possible to read one of many objects in a file without 
scanning all the preceding data. (In practice, pure stream I/O is adequate although random access 
makes it easier to write files.) Some programs need to read and play out their data in real time, so 
we need good compromises between generality and efficiency. 


As much as we need standards, they can’t hold up product schedules. So we also need a kind of 
decentralized extensibility where any software developer can define and refine new object types 
without some "standards authority" in the loop. Developers must be able to extend existing formats 
in a forward- and backward-compatible way. A central repository for design information and 
example programs can help us take full advantage of the standard. 


For convenience, data formats should heed the restrictions of various processors and environments. 
For example, word-alignment greatly helps 68000 access at insignificant cost to 8088 programs. 


Other goals include the ability to share common elements over a list of objects and the ability to 
construct composite objects. 


And finally, "Simple things should be simple and complex things should be possible" - Alan Kay. 


Think Ahead 


Let’s think ahead and build programs that read and write files for each other and for programs yet to 
be designed. Build data formats to last for future computers so long as the overhead is acceptable. 
This extends the usefulness and life of today’s programs and data. 


To maximize interconnectivity, the standard file structure and the specific object formats must all 
be general and extensible. Think ahead when designing an object. File formats should serve many 
purposes and allow many programs to store and read back all the information they need; even 
squeeze in custom data. Then a programmer can store the available data and is encouraged to 
include fixed contextual details. Recipient programs can read the needed parts, skip unrecognized 
stuff, default missing data, and use the stored context to help transform the data as needed. 


Scope 


IFF addresses these needs by defining a standard file structure, some initial data object types, ways 
to define new types, and rules for accessing these files. We can accomplish a great deal by writing 
programs according to this standard, but do not expect direct compatibility with existing software. 
We’ll need conversion programs to bridge the gap from the old world. 


IFF Specification 357 


IFF is geared for computers that readily process information in 8-bit bytes. It assumes a "physical 
layer" of data storage and transmission that reliably maintains "files" as sequences of 8-bit bytes. 
The standard treats a "file" as a container of data bytes and is independent of how to find a file and 
whether it has a byte count. 


This standard does not by itself implement a clipboard for cutting and pasting data between programs. 
A clipboard needs software to mediate access, and provide a notification mechanism so updates and 
requests for data can be detected. 


Data Abstraction 


The basic problem is how to represent information in a way that’s program-independent, compiler- 
independent, machine-independent, and device-independent. 


The computer science approach is "data abstraction", also known as "objects", "actors", and "abstract 
data types". A data abstraction has a "concrete representation" (its storage format), an "abstract 
representation" (its capabilities and uses), and access procedures that isolate all the calling software 
from the concrete representation. Only the access procedures touch the data storage. Hiding mutable 
details behind an interface is called "information hiding". What is hidden are the non-portable 
details of implementing the object, namely the selected storage representation and algorithms for 
manipulating it. 


The power of this approach is modularity. By adjusting the access procedures we can extend and 
restructure the data without impacting the interface or its callers. Conversely, we can extend and 
restructure the interface and callers without making existing data obsolete. It’s great for interchange! 


But we seem to need the opposite: fixed file formats for all programs to access. Actually, we could 
file data abstractions ("filed objects") by storing the data and access procedures together. We’d 
have to encode the access procedures in a standard machine-independent programming language a 
la PostScript. Even with this, the interface can’t evolve freely since we can’t update all copies of 
the access procedures. So we’ll have to design our abstract representations for limited evolution 
and occasional revolution (conversion). 


In any case, today’s microcomputers can’t practically store true data abstractions. They can do 
the next best thing: store arbitrary types of data in "data chunks", each with a type identifier and 
a length count. The type identifier is a reference by name to the access procedures (any local 
implementation). The length count enables storage-level object operations like "copy" and "skip to 
next" independent of object type or contents. 


Chunk writing is straightforward. Chunk reading requires a trivial parser to scan each chunk and 
dispatch to the proper access/conversion procedure. Reading chunks nested inside other chunks 
may require recursion, but no look ahead or backup. 


That’s the main idea of IFF. There are, of course, a few other details... 


358 Amiga ROM Kernel Reference Manual: Devices 


Previous Work 
Where our needs are similar, we borrow from existing standards. 


Our basic need to move data between independently developed programs is similar to that addressed 
by the Apple Macintosh desk scrap or "clipboard" [Inside Macintosh chapter "Scrap Manager"). 
The Scrap Manager works closely with the Resource Manager, a handy filer and swapper for data 
objects (text strings, dialog window templates, pictures, fonts) including types yet to be designed 
[Inside Macintosh chapter "Resource Manager"]. The Resource Manager is akin to Smalltalk’s 
object swapper. 





We will probably write a Macintosh desk accessory that converts IFF files to and from the Macintosh 
clipboard for quick and easy interchange with programs like MacPaint and Resource Mover. 


Macintosh uses a simple and elegant scheme of four-character "identifiers" to identify resource 
types, clipboard format types, file types, and file creator programs. Alternatives are unique ID 
numbers assigned by a central authority or by hierarchical authorities, unique ID numbers generated 
by algorithm, other fixed length character strings, and variable length strings. Character string 
identifiers double as readable signposts in data files and programs. The choice of 4 characters is a 
good tradeoff between storage space, fetch/compare/store time, and name space size. We'll honor 
Apple’s designers by adopting this scheme. 


"PICT" is a good example of a standard structured graphics format (including raster images) and its 
many uses [Inside Macintosh chapter "QuickDraw"]. Macintosh provides QuickDraw routines in 
ROM to create, manipulate, and display PICTs. Any application can create a PICT by simply asking 
QuickDraw to record a sequence of drawing commands. Since it’s just as easy to ask QuickDraw 
to render a PICT to a screen or a printer, it’s very effective to pass them between programs, say 
from an illustrator to a word processor. An important feature is the ability to store "comments" in a 
PICT which QuickDraw will ignore. (Actually, it passes them to your optional custom "comment 
handler".) 


PostScript, Adobe System’s print file standard, is a more general way to represent any print image 
(which is a specification for putting marks on paper) [PostScript Language Manual]. In fact, 
PostScript is a full-fledged programming language. To interpret a PostScript program is to render a 
document on a raster output device. The language is defined in layers: a lexical layer of identifiers, 
constants, and operators; a layer of reverse polish semantics including scope rules and a way 
to define new subroutines; and a printing-specific layer of built-in identifiers and operators for 
rendering graphic images. It is clearly a powerful (Turing equivalent) image definition language. 
PICT and a subset of PostScript are candidates for structured graphics standards. 


A PostScript document can be printed on any raster output device (including a display) but cannot 
generally be edited. That’s because the original flexibility and constraints have been discarded. 
Besides, a PostScript program may use arbitrary computation to supply parameters like placement 
and size to each operator. A QuickDraw PICT, in comparison, is a more restricted format of graphic 
primitives parameterized by constants. So a PICT can be edited at the level of the primitives, e.g., 
move or thicken a line. It cannot be edited at the higher level of, say, the bar chart data which 
generated the picture. 


IFF Specification 359 


PostScript has another limitation: not all kinds of data amount to marks on paper. A musical 
instrument description is one example. PostScript is just not geared for such uses. 


"DIF" is another example of data being stored in a general format usable by future programs [DIF 
Technical Specification]. DIF is a format for spreadsheet data interchange. DIF and PostScript are 
both expressed in plain ASCII text files. This is very handy for printing, debugging, experimenting, 
and transmitting across modems. It can have substantial cost in compaction and read/write work, 
depending on use. We won’t store IFF files this way but we could define an ASCII alternate 
representation with a converter program. 


InterScript is the Xerox standard for interchange of editable documents [Introduction to InterScript]. 
It approaches a harder problem: How to represent editable word processor documents that may 
contain formatted text, pictures, cross-references like figure numbers, and even highly specialized 
objects like mathematical equations? InterScript aims to define one standard representation for 
each kind of information. Each InterScript-compatible editor is supposed to preserve the objects it 
doesn’t understand and even maintain nested cross-references. So a simple word processor would 
let you edit the text of a fancy document without discarding the equations or disrupting the equation 
numbers. 


Our task is similarly to store high level information and preserve as much content as practical while 
moving it between programs. But we need to span a larger universe of data types and cannot expect 
to centrally define them all. Fortunately, we don’t need to make programs preserve information 
that they don’t understand. And for better or worse, we don’t have to tackle general-purpose 
cross-references yet. 


360 Amiga ROM Kernel Reference Manual: Devices 


3. Primitive Data Types 


Atomic components such as integers and characters that are interpretable directly by the CPU are 
specified in one format for all processors. We chose a format that’s the same as used by the Motorola 
MC68000 processor [M68000 16/32-Bit Microprocessor Programmer’s Reference Manual]. The 
high byte and high word of a number are stored first. 


N.B.: Part 3 dictates the format for "primitive" data types where—and only where—used in the 
overall file structure. The number of such occurrences of dictated formats will be small enough that 
the costs of conversion, storage, and management of processor-specific files would far exceed the 
costs of conversion during I/O by "foreign" programs. A particular data chunk may be specified with 
a different format for its internal primitive types or with processor or environment specific variants 
if necessary to optimize local usage. Since that hurts data interchange, it’s not recommended. (Cf. 
Designing New Data Sections, in Part 4.) 


Alignment 


All data objects larger than a byte are aligned on even byte addresses relative to the start of the 
file. This may require padding. Pad bytes are to be written as zeros, but don’t count on that when 
reading. 


This means that every odd-length "chunk" must be padded so that the next one will fall on an even 
boundary. Also, designers of structures to be stored in chunks should include pad fields where 
needed to align every field larger than a byte. For best efficiency, long word data should be arranged 
on long word (4 byte) boundaries. Zeros should be stored in all the pad bytes. 


Justification: Even-alignment causes a little extra work for files that are used only on certain 
processors but allows 68000 programs to construct and scan the data in memory and do block I/O. 
Any 16-bit or greater CPU will have faster access to aligned data. You just add an occasional pad 
field to data structures that you’re going to block read/write or else stream read/write an extra byte. 
And the same source code works on all processors. Unspecified alignment, on the other hand, 
would force 68000 programs to (dis)assemble word and long word data one byte at a time. Pretty 
cumbersome in a high level language. And if you don’t conditionally compile that step out for other 
processors, you won’t gain anything. 


Numbers 


Numeric types supported are two’s complement binary integers in the format used by the MC68000 
processor—high byte first, high word first—the reverse of 8088 and 6502 format. 

UBYTE 8 bits unsigned 

WORD 16 bits signed 


UWORD 16 bits unsigned 
LONG 32 bits signed 


The actual type definitions depend on the CPU and the compiler. In this document, we’ll express 
data type definitions in the C programming language. [See C, A Reference Manual.] In 68000 
Lattice C: 


typedef unsigned char UBYTE; /* 8 bits unsigned */ 
typedef short WORD; /* 16 bits signed */ 
typedef unsigned short UWORD; /* 16 bits unsigned */ 
typedef long LONG; /* 32 bits signed */ 


IFF Specification 361 


Characters 


The following character set is assumed wherever characters are used, e.g., in text strings, IDs, and 
TEXT chunks (see below). Characters are encoded in 8-bit ASCII. Characters in the range NUL 
(hex 0) through DEL (hex 7F) are well defined by the 7-bit ASCII standard. IFF uses the graphic 
group " " (SP, hex 20) through "™ (hex 7E). 


Most of the control character group hex 01 through hex 1F have no standard meaning in IFF. The 
control character LF (hex OA) is defined as a "newline" character. It denotes an intentional line 
break, that is, a paragraph or line terminator. (There is no way to store an automatic line break. That 
is strictly a function of the margins in the environment the text is placed.) The control character 
ESC (hex 1B) is a reserved escape character under the rules of ANSI standard 3.64-1979 American 








standard 6429.2. 


Characters in the range hex 7F through hex FF are not globally defined in IFF. They are best left 
reserved for future standardization. (Note that the FORM type FTXT (formatted text) defines the 
meaning of these characters within FTXT forms.) In particular, character values hex 7F through 
hex 9F are control codes while characters hex AO through hex FF are extended graphic characters 
like ©, as per the ISO and ANSI standards cited above. [See the supplementary document "FT XT" 
IFF Formatted Text.] 


Dates 


A "creation date" is defined as the date and time a stream of data bytes was created. (Some systems 
call this a "last modified date".) Editing some data changes its creation date. Moving the data 
between volumes or machines does not. 


The IFF standard date format will be one of those used in MS-DOS, Macintosh, or AmigaDOS 
(probably a 32-bit unsigned number of seconds since a reference point). Issue: Investigate these 
three. 


Type IDs 


A "type ID", "property name", "FORM type", or any other IFF identifier is a 32-bit value: the 
concatenation of four ASCII characters in the range " " (SP, hex 20) through "“" (hex 7E). Spaces 
(hex 20) should not precede printing characters; trailing spaces are OK. Control characters are 
forbidden. 


typedef CHAR ID[4]; 


IDs are compared using a simple 32-bit case-dependent equality test. FORM type IDs are restricted. 
Since they may be stored in filename extensions lower case letters and punctuation marks are 
forbidden. Trailing spaces are OK. 


Carefully choose those four characters when you pick a new ID. Make them mnemonic so pro- 
grammers can look at an interchange format file and figure out what kind of data it contains. The 
name space makes it possible for developers scattered around the globe to generate ID values with 
minimal collisions so long as they choose specific names like "MUS4" instead of general ones like 
"TYPE" and "FILE". 


362 Amiga ROM Kernel Reference Manual: Devices 


Commodore Applications and Technical Support has undertaken the task of maintaining the registry 
of FORM type IDs and format descriptions. See the IFF registry document for more information. 


Sometimes it’s necessary to make data format changes that aren’t backward compatible. As much 
as we work for compatibility, unintended interactions can develop. Since IDs are used to denote 
data formats in IFF, new IDs are chosen to denote revised formats. Since programs won't read 
chunks whose IDs they don’t recognize (see Chunks, below), the new IDs keep old programs from 
stumbling over new data. The conventional way to chose a "revision" ID is to increment the last 
character if it’s a digit or else change the last character to a digit. E.g., first and second revisions of 
the ID "XY" would be "XY1" and "XY2". Revisions of "CMAP" would be "CMA1" and "CMA2". 


Chunks 
Chunks are the building blocks in the IFF structure. The form expressed as a C typedef is: 


typedef struct { 
ID 


ckID; /* 4 character ID */ 
LONG ckSize; /* sizeof(ckData) */ 
UBYTE ckData[/* ckSize */]; 
} Chunk; 


We can diagram an example chunk — a "CMAP" chunk containing 12 data bytes — like this: 


ckID: 


ckSize: 


ckData: ' 





That’s 4 bytes of ckID, 4 bytes of ckSize and 12 data bytes. The total space used is 20 bytes. 


The ckID identifies the format and purpose of the chunk. As a rule, a program must recognize 
ckID to interpret ckData. It should skip over all unrecognized chunks. The ckID also serves as a 
format version number as long as we pick new IDs to identify new formats of ckData (see above). 


The following ckIDs are universally reserved to identify chunks with particular IFF meanings: 
"LIST", "FORM", "PROP", "CAT", and" ". The specialID" " (4 spaces) is a ckID for "filler" 
chunks, that is, chunks that fill space but have no meaningful contents. The IDs "LIS1" through 
"LIS9", "FOR1" through "FOR9", and "CAT1" through "CAT9" are reserved for future "version 
number" variations. All IFF-compatible software must account for these chunk IDs. 


The ckSize is a logical block size—how many data bytes areinckData. If ckData is an odd 
number of bytes long, a 0 pad byte follows which is not included in ckSize. (Cf. Alignment.) A 
chunk’s total physical size is ckSize rounded up to an even number plus the size of the header. So 
the smallest chunk is 8 bytes long with ckSize = 0. For the sake of following chunks, programs 
must respect every chunk’s ckSize as a virtual end-of-file for reading its ckData even if that data 
is malformed, e.g., if nested contents are truncated. 


IFF Specification 363 


We can describe the syntax of a chunk as a regular expression with "#" representing the ckSize, 
the length of the following braced bytes. The "[0]" represents a sometimes needed pad byte. (The 
regular expressions in this document are collected in Appendix A along with an explanation of 
notation.) 


Chunk ::= ID #{ UBYTE* } [0] 


One chunk output technique is to stream write a chunk header, stream write the chunk contents, 
then random access back to the header to fill in the size. Another technique is to make a preliminary 
pass over the data to compute the size, then write it out all at once. 


Strings, String Chunks, and String Properties 


In a string of ASCII text, linefeed (Ox0A) denotes a forced line break (paragraph or line terminator). 
Other control characters are not used. (Cf. Characters.) For maximum compatibility with line 
editors, two linefeed characters are often used to indicate a paragraph boundary. 


The ckID for a chunk that contains a string of plain, unformatted text is "TEXT". As a practical 
matter, a text string should probably not be longer than 32767 bytes. The standard allows up to 23! 
- 1 bytes. The ckID "TEXT" is globally reserved for this use. 


When used as a data property (see below), a text string chunk may be 0 to 255 characters long. 
Such a string is readily converted to a C string or a Pascal STRING[255]. The ckID of a property 
must have a unique property name, not "TEXT". 


When used as a part of a chunk or data property, restricted C string format is normally used. That 
means 0 to 255 characters followed by a NULL byte (ASCII value 0). 


Data Properties (advanced topic) 


Data properties specify attributes for following (non-property) chunks. A data property essentially 
says "identifier = value", for example "XY = (10, 200)", telling something about following chunks. 
Properties may only appear inside data sections ("FORM" chunks, cf. Data Sections) and property 
sections ("PROP" chunks, cf. Group PROP). 


The form of a data property is a type of Chunk. The ckID is a property name as well as a property 
type. The ckSize should be small since data properties are intended to be accumulated in RAM 
when reading a file. (256 bytes is a reasonable upper bound.) Syntactically: 


Property ::= Chunk 


When designing a data object, use properties to describe context information like the size of an 
image, even if they don’t vary in your program. Other programs will need this information. 


Think of property settings as assignments to variables in a programming language. Multiple 
assignments are redundant and local assignments temporarily override global assignments. The 
order of assignments doesn’t matter as long as they precede the affected chunks. (Cf. LISTs, CATs, 
and Shared Properties.) 


Each object type (FORM type) is a local name space for property IDs. Think of a "CMAP" property 
in a "FORM ILBM" as the qualified ID "ILBM.CMAP". A "CMAP" inside some other type of 
FORM may not have the same meaning. Property IDs specified when an object type is designed 


364 Amiga ROM Kernel Reference Manual: Devices 


(and therefore known to all clients) are called "standard" while specialized ones added later are 
"nonstandard". 


Links 


Issue: A standard mechanism for "links" or "cross references" is very desirable for things like 
combining images and sounds into animations. Perhaps we’ll define "link" chunks within FORMs 
that refer to other FORMs or to specific chunks within the same and other FORMs. This needs 
further work. EA IFF 1985 has no standard link mechanism. 


For now, it may suffice to read a list of, say, musical instruments, and then just refer to them within 
a musical score by sequence number. 


File References 


Issue: We may need a standard form for references to other files. A "file ref" could name a directory 
and a file in the same type of operating system as the reference’s originator. Following the reference 
would expect the file to be on some mounted volume, or perhaps the same directory as the file that 
made the reference. In a network environment, a file reference could name a server, too. 


Issue: How can we express operating-system independent file references? 


Issue: What about a means to reference a portion of another file? Would this be a "file ref" plus a 
reference to a "link" within the target file? 


IFF Specification 365 


4. Data Sections 
The first thing we need of a file is to check: Does it contain IFF data and, if so, does it contain the 
kind of data we’re looking for? So we come to the notion of a "data section". 


A "data section" or IFF "FORM" is one self-contained "data object" that might be stored in a file by 
itself. It is one high level data object such as a picture or a sound effect, and generally contains a 
grouping of chunks. The IFF structure "FORM" makes it self-identifying. It could be a composite 
object like a musical score with nested musical instrument descriptions. 


Group FORM 
A data section is a chunk with ckID "FORM" and this arrangement: 


FORM = "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* } 
FormType ::= ID 
LocalChunk ::= Property | Chunk 


The ID "FORM" is a syntactic keyword like "struct" in C. Think of a "struct ILBM"” containing a 
field "CMAP". If you see "FORM" you will know to expect a FORM type ID (the structure name, 
"ILBM” in this example) and a particular contents arrangement or "syntax" (local chunks, FORMs, 
LISTs, and CATs). A "FORM ILBM", in particular, might contain a local chunk "CMAP", an 
"ILBM.CMAP" (to use a qualified name). 


So the chunk ID "FORM" indicates a data section. It implies that the chunk contains an ID and 
some number of nested chunks. In reading a FORM, like any other chunk, programs must respect 
its ckSize as a virtual end-of-file for reading its contents, even if they’re truncated. 


The FORM type is a restricted ID that may not contain lower case letters or punctuation characters. 
(Cf. Type IDs. Cf. Single Purpose Files.) 


The type-specific information in a FORM is composed of its "local chunks": data properties and 
other chunks. Each FORM type is a local name space for local chunk IDs. So "CMAP" local chunks 
in other FORM types may be unrelated to "ILBM.CMAP". More than that, each FORM type defines 
semantic scope. If you know what a FORM ILBM is, you will know what an ILBM.CMAP is. 


Local chunks defined when the FORM type is designed (and therefore known to all clients of this 
type) are called "standard" while specialized ones added later are "nonstandard". 


Among the local chunks, property chunks give settings for various details like text font while the 
other chunks supply the essential information. This distinction is not clear cut. A property setting 
can be cancelled by a later setting of the same property. E.g., in the sequence: 


propl = x (Data A) propl = z_ propl = y (Data B) 


prop! is = x for Data A, and y for Data B. The setting prop1 = z has no effect. 


For clarity, the universally reserved chunk IDs "LIST", "FORM", "PROP", "CAT ","  ", "LIS1" 
through "LIS9", "FOR1" through "FOR9", and "CAT 1" through "CAT9" may not be FORM type 
IDs. 


Part 5, below, talks about grouping FORMs into LISTs and CATs. They let you group a bunch of 
FORMs but don’t impose any particular meaning or constraints on the grouping. Read on. 


366 Amiga ROM Kernel Reference Manual: Devices 


Composite FORMs 


A FORM chunk inside a FORM is a full-fledged data section. This means you can build a composite 
object such as a multi-frame animation sequence by nesting available picture FORMs and sound 
effect FORMs. You can insert additional chunks with information like frame rate and frame count. 


Using composite FORMs, you leverage on existing programs that create and edit the component 
FORMs. Those editors may even look into your composite object to copy out its type of component. 
Such editors are not allowed to replace their component objects within your composite object. That’s 
because the IFF standard lets you specify consistency requirements for the composite FORM such 
as maintaining a count or a directory of the components. Only programs that are written to uphold 
the rules of your FORM type may create or modify such FORMs. 


Therefore, in designing a program that creates composite objects, you are strongly requested to 
provide a facility for your users to import and export the nested FORMs. Import and export could 
move the data through a clipboard or a file. 


Here are several existing FORM types and rules for defining new ones: 


FTXT 


An FTXT data section contains text with character formatting information like fonts and faces. It 
has no paragraph or document formatting information like margins and page headers. FORM FT XT 
is well matched to the text representation in Amiga’s Intuition environment. See the supplemental 
document "FT XT" IFF Formatted Text. 


ILBM 


"ILBM" is an InterLeaved BitMap image with color map; a machine-independent format for raster 
images. FORM ILBM is the standard image file format for the Commodore-Amiga computer and is 
useful in other environments, too. See the supplemental document "ILBM" IFF Interleaved Bitmap. 


PICS 


The data chunk inside a "PICS" data section has ID "PICT" and holds a QuickDraw picture. Issue: 
Allow more than one PICT in a PICS? See Inside Macintosh chapter "QuickDraw” for details on 
PICTs and how to create and display them on the Macintosh computer. 


The only standard property for PICS is "XY", an optional property that indicates the position of the 
PICT relative to "the big picture". The contents of an XY is a QuickDraw Point. 


Note: PICT may be limited to Macintosh use, in which case there’ll be another format for structured 
graphics in other environments. 


Other Macintosh Resource Types 


Some other Macintosh resource types could be adopted for use within IFF files; perhaps MWRT, 
ICN, ICN#, and STR#. 


Issue: Consider the candidates and reserve some more IDs. 


IFF Specification 367 


Designing New Data Sections 


Supplemental documents will define additional object types. A supplement needs to specify the 
object’s purpose, its FORM type ID, the IDs and formats of standard local chunks, and rules for 
generating and interpreting the data. It’s a good idea to supply typedefs and an example source 
program that accesses the new object. See "ILBM" IFF Interleaved Bitmap for such an example. 


Anyone can pick a new FORM type ID but should reserve it with Commodore Applications and 
Technical Support (CATS) at their earliest convenience. While decentralized format definitions and 
extensions are possible in IFF, our preference is to get design consensus by committee, implement 
a program to read and write it, perhaps tune the format before it becomes locked in stone, and then 
publish the format with example code. Some organization should remain in charge of answering 
questions and coordinating extensions to the format. 


If it becomes necessary to incompatibly revise the design of some data section, its FORM type ID 
will serve as a version number (Cf. Type IDs). E.g., a revised "VDEO" data section could be called 
"VDE1". But try to get by with compatible revisions within the existing FORM type. 


In a new FORM type, the rules for primitive data types and word-alignment (Cf. Primitive Data 
Types) may be overridden for the contents of its local chunks — but not for the chunk structure itself 
— if your documentation spells out the deviations. If machine-specific type variants are needed, 
€.g., to store vast numbers of integers in reverse bit order, then outline the conversion algorithm and 
indicate the variant inside each file, perhaps via different FORM types. Needless to say, variations 
should be minimized. 


In designing a FORM type, encapsulate all the data that other programs will need to interpret your 
files. E.g., a raster graphics image should specify the image size even if your program always uses 
320 x 200 pixels x 3 bitplanes. Receiving programs are then empowered to append or clip the image 
rectangle, to add or drop bitplanes, etc. This enables a lot more compatibility. 


Separate the central data (like musical notes) from more specialized information (like note beams) 
so simpler programs can extract the central parts during read-in. Leave room for expansion so other 
programs can squeeze in new kinds of information (like lyrics). And remember to keep the property 
chunks manageably short—let’s say < 256 bytes. 


When designing a data object, try to strike a good tradeoff between a super- general format and a 
highly-specialized one. Fit the details to at least one particular need, for example a raster image 
might as well store pixels in the current machine’s scan order. But add the kind of generality that 
makes the format usable with foreseeable hardware and software. E.g., use a whole byte for each 
red, green, and blue color value even if this year’s computer has only 4-bit video DACs. Think 
ahead and help other programs so long as the overhead is acceptable. E.g., ran compress a raster 
by scan line rather than as a unit so future programs can swap images by scan line to and from 
secondary storage. 


Try to design a general purpose "least common multiple” format that encompasses the needs of 
many programs without getting too complicated. Be sure to leave provisions for future expansion. 
Let’s coalesce our uses around a few such formats widely separated in the vast design space. Two 
factors make this flexibility and simplicity practical. First, file storage space is getting very plentiful, 
so compaction is not always a priority. Second, nearly any locally-performed data conversion work 
during file reading and writing will be cheap compared to the I/O time. 


368 Amiga ROM Kernel Reference Manual: Devices 


It must be permitted to copy a LIST or FORM or CAT intact, e.g., to incorporate it into a composite 
FORM. So any kind of internal references within a FORM must be relative references. They could 
be relative to the start of the containing FORM, relative from the referencing chunk, or a sequence 
number into a collection. 


With composite FORMs, you leverage on existing programs that create and edit the components. 
If you write a program that creates composite objects, please provide a facility for users to import 
and export the nested FORMs. 


Finally, don’t forget to specify all implied rules in detail. 


IFF Specification 369 


5. LISTs, CATs, and Shared Properties (Advanced topics) 


Data often needs to be grouped together, for example, consider a list of icons. Sometimes a trick 
like arranging little images into a big raster works, but generally they’ll need to be structured as a 
first class group. The objects "LIST" and "CAT " are IFF-universal mechanisms for this purpose. 
Note: LIST and CAT are advanced topics the first time reader will want to skip. 


Property settings sometimes need to be shared over a list of similar objects. E.g., a list of icons may 
share one color map. LIST provides a means called "PROP" to do this. One purpose of a LIST is 
to define the scope of a PROP. A "CAT ", on the other hand, is simply a concatenation of objects. 


Simpler programs may skip LISTs and PROPs altogether and just handle FORMs and CATs. All 
"fully-conforming" IFF programs also know about "CAT ", "LIST", and "PROP". Any program 
that reads a FORM inside a LIST must process shared PROPs to correctly interpret that FORM. 


Group CAT 
A CAT is just an untyped group of data objects. 


Structurally, a CAT is a chunk with chunk ID "CAT " containing a "contents type" ID followed by 
the nested objects. The ckSize of each contained chunk is essentially a relative pointer to the next 
one. 


CAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* } 
ContentsType ::= ID -- a hint or an "abstract data type" ID 


In reading a CAT, like any other chunk, programs must respect its ckSize as a virtual end-of-file 
for reading the nested objects even if they’re malformed or truncated. 


The "contents type" following the CAT’s ckSize indicates what kind of FORMs are inside. So a 
CAT of ILBMs would store "ILBM" there. It’s just a hint. It may be used to store an "abstract data 
type". A CAT could just have blank contents ID ("__") if it contains more than one kind of FORM. 


CAT defines only the format of the group. The group’s meaning is open to interpretation. This 
is like a list in LISP: the structure of cells is predefined but the meaning of the contents as, say, 
an association list depends on use. If you need a group with an enforced meaning (an "abstract 
datatype” or Smalltalk "subclass"), some consistency constraints, or additional data chunks, use a 
composite FORM instead (Cf. Composite FORMs). 


Since a CAT just means a concatenation of objects, CATs are rarely nested. Programs should really 
merge CATs rather than nest them. 





Group LIST 


A LIST defines a group very much like CAT but it also gives a scope for PROPs (see below). And 
unlike CATs, LISTs should not be merged without understanding their contents. 


Structurally, a LIST is a chunk with ckID "LIST" containing a "contents type" ID, optional shared 
properties, and the nested contents (FORMs, LISTs, and CATs), in that order. The ckSize of each 
contained chunk is a relative pointer to the next one. A LIST is not an arbitrary linked list—the 
cells are simply concatenated. 


LIST 


3 "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* } 
ContentsType :: 


ID 


eee 
woul 


370 Amiga ROM Kernel Reference Manual: Devices 


Group PROP 


PROP chunks may appear in LISTs (not in FORMs or CATs). They supply shared properties for 
the FORMs in that LIST. This ability to elevate some property settings to shared status for a list of 
forms is useful for both indirection and compaction. E.g., a list of images with the same size and 
colors can share one "size" property and one "color map" property. Individual FORMs can override 
the shared settings. 


The contents of a PROP is like a FORM with no data chunks: 


PROP s:= "PROP" #{ FormType Property* } 


It means, "Here are the shared properties for FORM type <FormType>". 


A LIST may have at most one PROP of a FORM type, and all the PROPs must appear before any of 
the FORMs or nested LISTs and CATs. You can have subsequences of FORMs sharing properties 
by making each subsequence a LIST. 


Scoping: Think of property settings as variable bindings in nested blocks of a programming 
language. In C this would look like: 


#define Roman 0 
#define Helvetica 1 


void main() 

{ 

int font=Roman; /* The global default */ 
printf("The font number is %d\n", font); 
} 
{ 
int font=Helvetica; /* local setting */ 
printf("The font number is %d\n", font); 
} 


{ 
printf("The font number is %d\n", font); 
} 


/* 
* Sample output: The font number is 0 
* The font number is 1 
* The font number is 0 
*/ 
An IFF file could contain: 
LIST { 
PROP TEXT { 
FONT {TimesRoman} /* shared setting x/ 
} 
FORM TEXT { 
FONT {Helvetica} /* local setting */ 
CHRS {Hello } /* uses font Helvetica */ 
} 
FORM TEXT { 
CHRS {there.} /* uses font TimesRoman */ 


} 


IFF Specification 371 


The shared property assignments selectively override the reader’s global defaults, but only for 
FORMs within the group. A FORM’s own property assignments selectively override the global 
and group-supplied values. So when reading an IFF file, keep property settings on a stack. They 
are designed to be small enough to hold in main memory. 


Shared properties are semantically equivalent to copying those properties into each of the nested 
FORMs right after their FORM type IDs. 


Properties for LIST 


Optional "properties for LIST" store the origin of the list’s contents in a PROP chunk for the 
pseudo FORM type "LIST". They are the properties originating program "OPGM", processor 
family "OCPU", computer type "OCMP", computer serial number or network address "OSN ", and 
user name "UNAM". In our imperfect world, these could be called upon to distinguish between 
unintended variations of a data format or to work around bugs in particular originating/receiving 
program pairs. Issue: Specify the format of these properties. 


A creation date could also be stored in a property, but let’s ask that file creating, editing, and 
transporting programs maintain the correct date in the local file system. Programs that move files 
between machine types are expected to copy across the creation dates. 


372 Amiga ROM Kernel Reference Manual: Devices 


6. Standard File Structure 
File Structure Overview 


An IFF file is just a single chunk of type FORM, LIST, or CAT. Therefore an IFF file can be 
recognized by its first 4 bytes: "FORM", "LIST", or "CAT ". Any file contents after the chunk’s 
end are to be ignored. (Some file transfer programs add garbage to the end of transferred files. This 
specification protects against such common damage). 


The simplest IFF file would be one that does no more than encapsulate some binary data (perhaps 
even an old-fashioned single-purpose binary file). Here is a binary dump of such a minimal IFF 
example: 

0000: 464F524D 0000001A 534E4150 43524143 FORM... .SNAPCRAC 


0010: OO000000D 68656C6C 6F2C776F 726C6421 ...-hello,world! 
0020: OA0O oe 


The first 4 bytes indicate this is a "FORM"; the most common IFF top level structure. The following 
4 bytes indicate that the contents totals 26 bytes. The form type is listed as "SNAP". 


Our form "SNAP" contains only one chunk at the moment; a chunk of type "CRAC". From the size 
($0000000D) the amount of data must be 13 bytes. In this case, the data happens to correspond to 
the ASCII string "hello, world! <If>". Since the number 13 is odd, a zero pad byte is added to 
the file. At any time new chunks could be added to form SNAP without affecting any other aspect 
of the file (other than the form size). It’s that simple. 


Since an IFF file can be a group of objects, programs that read/write single objects can communicate 
to an extent with programs that read/write groups. You’re encouraged to write programs that handle 
all the objects in a LIST or CAT. A graphics editor, for example, could process a list of pictures as 
a multiple page document, one page at a time. 


Programs should enforce IFF’s syntactic rules when reading and writing files. Users should be 
told when a file is corrupt. This ensures robust data transfer. For minor damage, you may wish to 
give the user the option of using the suspect data, or cancelling. Presumably a user could read in a 
damaged file, then save whatever was salvaged to a valid file. The public domain IFF reader/writer 
subroutine package does some syntactic checks for you. A utility program"IFFCheck" is available 
that scans an IFF file and checks it for conformance to IFF’s syntactic rules. IFFCheck also prints 
an outline of the chunks in the file, showing the ckID and ckSize of each. This is quite handy 
when building IFF programs. Example programs are also available to show details of reading and 
writing IFF files. 


A merge program "IFFJoin" will be available that logically appends IFF files into a single CAT 
group. It "unwraps" each input file that is a CAT so that the combined file isn’t nested CATs. 


If we need to revise the IFF standard, the three anchoring IDs will be used as "version numbers". 
That’s why IDs "FOR1" through "FOR9", "LIS1" through "LIS9", and "CAT1" through "CAT9" 
are reserved. 


IFF formats are designed for reasonable performance with floppy disks. We achieve considerable 
simplicity in the formats and programs by relying on the host file system rather than defining 
universal grouping structures like directories for LIST contents. On huge storage systems, IFF files 
could be leaf nodes in a file structure like a B-tree. Let’s hope the host file system implements that 
for us! 


IFF Specification 373 


There are two kinds of IFF files: single purpose files and scrap files. They differ in the interpretation 
of multiple data objects and in the file’s external type. 


Single Purpose Files 


A single purpose IFF file is for normal "document" and "archive" storage. This is in contrast with 
"scrap files" (see below) and temporary backing storage (non-interchange files). 


The external file type (or filename extension, depending on the host file system) indicates the file’s 
contents. It’s generally the FORM type of the data contained, hence the restrictions on FORM type 
IDs. 


Programmers and users may pick an "intended use" type as the filename extension to make it easy 
to filter for the relevant files in a filename requester. This is actually a "subclass" or "subtype" 
that conveniently separates files of the same FORM type that have different uses. Programs cannot 
demand conformity to its expected subtypes without overly restricting data interchange since they 
cannot know about the subtypes to be used by future programs that users will want to exchange data 
with. 


Issue: How to generate 3-letter MS-DOS extensions from 4-letter FORM type IDs? 


Most single purpose files will be a single FORM (perhaps a composite FORM like a musical score 
containing nested FORMs like musical instrument descriptions). If it’s a LIST or a CAT, programs 
should skip over unrecognized objects to read the recognized ones or the first recognized one. Then 
a program that can read a single purpose file can read something out of a "scrap file", too. 


Scrap Files (not currently used) 


A "scrap file" is for maximum interconnectivity in getting data between programs; the core of a 
clipboard function. Scrap files may have type "IFF " or filename extension ".IFF". 


A scrap file is typically a CAT containing alternate representations of the same basic information. 
Include as many altematives as you can readily generate. This redundancy improves intercon- 
nectivity in situations where we can’t make all programs read and write super-general formats. 
[Inside Macintosh chapter "Scrap Manager".] E.g., a graphically-annotated musical score might be 
supplemented by a stripped down 4-voice melody and by a text (i.e., the lyrics). 





The originating program should write the alternate representations in order of "preference": most 
preferred (most comprehensive) type to least preferred (least comprehensive) type. A receiving 
program should either use the first appearing type that it understands or search for its own "preferred" 
type. 

A scrap file should have at most one alternative of any type. (A LIST of same type objects is OK 
as one of the alternatives.) But don’t count on this when reading; ignore extra sections of a type. 
Then a program that reads scrap files can read something out of single purpose files. 


374 Amiga ROM Kernel Reference Manual: Devices 


Rules for Reader Programs 


Here are some notes on building programs that read IFF files. For LIST and PROP work, you 
should also read up on recursive descent parsers. [See, for example, Compiler Construction, An 
Advanced Course.] 





e The standard is very flexible so many programs can exchange data. This implies a program has 
to scan the file and react to what’s actually there in whatever order it appears. An IFF reader 
program is a parser. 


For interchange to really work, programs must be willing to do some conversion during read- 
in. If the data isn’t exactly what you expect, say, the raster is smaller than those created by 
your program, then adjust it. Similarly, your program could crop a large picture, add or drop 
bitplanes, or create/discard a mask plane. The program should give up gracefully on data that 
it can’t convert. 


If it doesn’t start with "FORM", "LIST", or "CAT ", it’s not an IFF-85 file. 


e For any chunk you encounter, you must recognize its type ID to understand its contents. 


e For any FORM chunk you encounter, you must recognize its FORM type ID to understand the 
contained "local chunks". Even if you don’t recognize the FORM type, you can still scan it for 
nested FORMs, LISTs, and CATs of interest. 


e Don’t forget to skip the implied pad byte after every odd-length chunk, this is not included in 
the chunk count! 


e Chunk types LIST, FORM, PROP, and CAT are generic groups. They always contain a subtype 
ID followed by chunks. 


Readers ought to handle a CAT of FORMs in a file. You may treat the FORMs like document 
pages to sequence through, or just use the first FORM. 


e Many IFF readers completely skip LISTs. "Fully IFF-conforming" readers are those that handle 
LISTs, even if just to read the first FORM from a file. If you do look into a LIST, you must 
process shared properties (in PROP chunks) properly. The idea is to get the correct data or 
none at all. 


e 


The nicest readers are willing to look into unrecognized FORMs for nested FORM types that 
they do recognize. For example, a musical score may contain nested instrument descriptions 
and animation or desktop publishing files may contain still pictures. This extra step is highly 
recommended. 


Note to programmers: Processing PROP chunks is not simple! You'll need some background in 
interpreters with stack frames. If this is foreign to you, build programs that read/write only one 
FORM per file. For the more intrepid programmers, the next paragraph summarizes how to process 
LISTs and PROPs. 


Allocate a stack frame for every LIST and FORM you encounter and initialize it by copying the 
stack frame of the parent LIST or FORM. At the top level, you’ll need a stack frame initialized to 
your program’s global defaults. While reading each LIST or FORM, store all encountered properties 
into the current stack frame. In the example ShowILBM, each stack frame has a place for a bitmap 
header property ILBM.BMHD and a color map property ILBM.CMAP. When you finally get to the 
ILBM’s BODY chunk, use the property settings accumulated in the current stack frame. 


IFF Specification 375 


An alternate implementation would just member PROPs encountered, forgetting each on reaching 
the end of its scope (the end of the containing LIST). When a FORM XXXxX is encountered, scan the 
chunks in all rememberéd PROPs XXXxX, in order, as if they appeared before the chunks actually 
in the FORM XXXX. This gets trickier if you read FORMs inside of FORMs. 


Rules for Writer Programs 


Here are some notes on building programs that write IFF files, which is much easier than reading 
them. 


e An IFF file is a single FORM, LIST, or CAT chunk. 


e Any IFF-85 file must start with the 4 characters "FORM", "LIST", or "CAT ", followed by a 
LONG ckSize. There should be no data after the chunk end. 


e Chunk types LIST, FORM, PROP, and CAT are generic. They always contain a subtype ID 
followed by chunks. These three IDs are universally reserved, as are "LIS1" through "LIS9", 
"FOR1" through "FOR9", "CAT 1" through "CAT9", and" ". 


e Don’t forget to write a 0 pad byte after each odd-length chunk. 


Do not try to edit a file that you don’t know how to create. Programs may look into a file and 
copy out nested FORMs of types that they recognize, but they should not edit and replace the 
nested FORMs and not add or remove them. Breaking these rules could make the containing 
structure inconsistent. You may write a new file containing items you copied, or copied and 
modified, but don’t copy structural parts you don’t understand. 


e 


You must adhere to the syntax descriptions in Appendix A. E.g., PROPs may only appear inside 
LISTs. 


There are at least four common techniques for writing an IFF group: 


(1) build the data in a file mapped into virtual memory. 

(2) build the data in memory blocks and use block I/O. 

(3) stream write the data piecemeal and (don’t forget!) random access back 

to set the group (or FORM) length count. 

(4) make a preliminary pass to compute the length count then stream write the data. 


Issue: The standard disallows "blind" chunk copying for consistency reasons. Perhaps we can 
define a ckID convention for chunks that are OK to replicate without knowledge of the contents. 
Any such chunks would need to be internally consistent, and not be bothered by changed external 
references. 


Issue: Stream-writing an IFF FORM can be inconvenient. With random access files one can write 
all the chunks then go back to fix up the FORM size. With stream access, the FORM size must be 
calculated before the file is written. When compression is involved, this can be slow or inconvenient. 
Perhaps we can define an "END " chunk. The stream writer would use -1 ($FFFFFFFF) as the 
FORM size. The reader would follow each chunk, when the reader reaches an "END ", it would 
terminate the last -1 sized chunk. Certain new IFF FORMs could require that readers understand 
"END ". 


376 Amiga ROM Kernel Reference Manual: Devices 


7. Standards Committee 
The following people contributed to the design of this IFF standard: 


Bob "Kodiak" Bums, Commodore-Amiga 

R. J. Mical, Commodore-Amiga 

Jerry Morrison, Electronic Arts 

Greg Riker, Electronic Arts 

Steve Shaw, Electronic Arts 

Barry Walsh, Commodore-Amiga 

Oct, 1988 revision by Bryce Nesbitt, and Carolyn Scheppner, Commodore-Amiga 


Appendix A. Reference 
Type Definitions 


The following C typedefs describe standard IFF structures. Declarations to use in practice will vary 
with the CPU and compiler. For example, 68000 Lattice C produces efficient comparison code if 
we define ID as a"LONG". A macro "MakeID" builds these IDs at compile time. 


/* Standard IFF types, expressed in 68000 Lattice C. */ 
typedef unsigned char UBYTE; /* 8 bits unsigned */ 
typedef short WORD; /* 16 bits signed */ 
typedef unsigned short UWORD; /* 16 bits unsigned */ 
typedef long LONG; /* 32 bits signed */ 
typedef char ID[4]; /* 4 chars in ’ ' through '~! */ 
typedef struct { 

ID ckID; 

LONG ckSize; /* sizeof (ckData) x/ 

UBYTE ckData[/* ckSize */]; 

} Chunk; 


/* ID typedef and builder for 68000 Lattice C. */ 
typedef LONG ID; /* 4 chars in ’ ' through '~’ */ 


#define MakeID(a,b,c,d) ( (a)<<24 | (b)<<16 | (c)<<8 | (d) ) 


/* Globally reserved IDs. */ 

#define ID FORM MakeID(’F’,'’0’,’R’,'M’) 
#define ID LIST MakeID(’L’,’I’,'’S’,’T’) 
#define ID_PROP MakeID(’P’,’R’,'0','P’) 
#define ID CAT MakeID(’C’,‘A’,’T’,’ ") 
#define ID_FILLER MakeID(’ ’,’ %,’ %,*% ") 


Syntax Definitions 
Here’s a collection of the syntax definitions in this document. 
Chunk ::= ID #{ UBYTE* } [0] 
Property := Chunk 
FORM = "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* } 
FormType = ID 
LocalChunk = Property | Chunk 
CAT "CAT " #{ ContentsType (FORM | LIST | CAT)* } 


ContentsType ::= ID -- a hint or an "abstract data type" ID 


LIST 
PROP 


"LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* } 
"PROP" #{ FormType Property* } 


IFF Specification 377 


In this extended regular expression notation, the token "#" represents a count of the following 
braced data bytes. Literal items are shown in "quotes", [square bracketed items] are optional, and 
"*" means 0 or more instances. A sometimes-needed pad byte is shown as "[0]". 


Example Diagrams 


Here’s a box diagram for an example IFF file, a raster image FORM ILBM. This FORM contains a 
bitmap header property chunk BMHD, a color map property chunk CMAP, and a raster data chunk 
BODY. This particular raster is 320 x 200 pixels x 3 bit planes uncompressed. The "0" after the 
CMAP chunk represents a zero pad byte; included since the CMAP chunk has an odd length. The 
text to the right of the diagram shows the outline that would be printed by the IFFCheck utility 
program for this particular file. 


FORM 24070 ILBM 


\ILBM! 
‘BMHD’ 20 BMHD 20 
3205, 200;-05: 0 3p.0; 020) wan 
24070 ‘CMAP’ 21 .CMAP 21 
0, 0, 0; 32, 0, O; 64, 0, 0... 
24000 
.BODY 24000 





378 Amiga ROM Kernel Reference Manual: Devices 


This second diagram shows a LIST of two FORMs ILBM sharing a common BMHD property and 
a common CMAP property. Again, the text on the right is an outline 4 la FF Check. 


‘LIST’ 48114 LIST 48114 ILBM 


‘PROP’ 62 -PROP 62 ILBM 


320, 200, 0, 0, 3, 0, 0, 0... .BMHD 20 
0, 0, 0; 32, 0, 0; 64, 0, 0... .CMAP 21 
0 





-FORM 24012 ILBM 


. BODY 24000 


-FORM 24012 ILBM 


. BODY 24000 





IFF Specification 379 


"ILBM" IFF Interleaved Bitma 


Date: January 17, 1986 (CRNG data updated Oct, 1988 by Jerry Morrison) 

(Appendix E added and CAMG updated Oct, 1988 by Commodore-Amiga, Inc.) 
From: Jerry Morrison, Electronic Arts 
Status: Released and in use 


1. Introduction 


"EA IFF 85" is Electronic Arts’ standard for interchange format files. "ILBM" is a format for a 2 
dimensional raster graphics image, specifically an InterLeaved bitplane BitMap image with color 
map. An ILBM is an IFF "data section" or "FORM type", which can be an IFF file or a part of one. 
ILBM allows simple, highly portable raster graphic storage. 


An ILBM is an archival representation designed for three uses. First, a stand- alone image that 
specifies exactly how to display itself (resolution, size, color map, etc.). Second, an image intended 
to be merged into a bigger picture which has its own depth, color map, and so on. And third, 
an empty image with a color map selection or "palette" for a paint program. ILBM is also 
intended as a building block for composite IFF FORMs like "animation sequences" and "structured 
graphics". Some uses of ILBM will be to preserve as much information as possible across disparate 
environments. Other uses will be to store data for a single program or highly cooperative programs 
while maintaining subtle details. So we’re trying to accomplish a lot with this one format. 


This memo is the IFF supplement for FORM ILBM. Section 2 defines the purpose and format 
of property chunks bitmap header "BMHD", color map "CMAP", hotspot "GRAB", destination 
merge data "DEST", sprite information "SPRT", and Commodore Amiga viewport mode "CAMG". 
Section 3 defines the standard data chunk "BODY". These are the "standard" chunks. Section 
4 defines the non- standard data chunks. Additional specialized chunks like texture pattern can 
be added later. The ILBM syntax is summarized in Appendix A as a regular expression and in 
Appendix B as a box diagram. Appendix C explains the optional run encoding scheme. Appendix 
D names the committee responsible for this FORM ILBM standard. 


Details of the raster layout are given in part 3, "Standard Data Chunk". Some elements are based 
on the Commodore Amiga hardware but generalized for use on other computers. An alternative to 
ILBM would be appropriate for computers with true color data in each pixel, though the wealth of 
available ILBM images makes import and export important. 


Reference: 


IFF files. 

Amiga® is a registered trademark of Commodore-Amiga, Inc. 
Electronic Arts™ is a trademark of Electronic Arts. 
Macintosh™ is a trademark licensed to Apple Computer, Inc. 
MacPaint™ is a trademark of Apple Computer, Inc. 





IFF Specification: ILBM 381 


2. Standard Properties 


ILBM has several defined property chunks that act on the main data chunks. The required property 
"BMHD" and any optional properties must appear before any "BODY" chunk. (Since an ILBM has 
only one BODY chunk, any following properties would be superfluous.) Any of these properties 
may be shared over a LIST of several IBLMs by putting them in a PROP ILBM (See the EA IFF 
85 document). 


BMHD 


The required property "BMHD" holds a BitmapHeader as defined in the following documentation. 
It describes the dimensions of the image, the encoding used, and other data necessary to understand 
the BODY chunk to follow. 


typedef UBYTE Masking; /* Choice of masking technique. */ 
#define mskNone 0 
#define mskHasMask 1 


#define mskHasTransparentColor 2 
#define mskLasso 


typedef UBYTE Compression; /* Choice of compression algorithm 
applied to the rows of all source and mask planes. "cmpByteRunl" 
is the byte run encoding described in Appendix C. Do not compress 
across rows! */ 


#define cmpNone 0 

#define cmpByteRunl 1 

typedef struct { 
UWORD w, h; /* raster width & height in pixels */ 
WORD xX, Ye /* pixel position for this image */ 
UBYTE nPlanes; /* # source bitplanes */ 
Masking masking; 
Compression compression; 
UBYTE padl; /* unused; ignore on read, write as 0 */ 
UWORD transparentColor; /* transparent "color number" (sort of) */ 
UBYTE xAspect, yAspect; /* pixel aspect, a ratio width : height */ 
WORD pageWidth, pageHeight; /* source "page" size in pixels */ 


} BitmapHeader; 


Fields are filed in the order shown. The UBYTE fields are byte-packed (the C compiler must not 
add pad bytes to the structure). 


The fields w and h indicate the size of the image rectangle in pixels. Each row of the image is stored 
in an integral number of 16 bit words. The number of words per row is words=((wt+15) /16) 
or Ceiling(w/16). The fields x and y indicate the desired position of this image within the 
destination picture. Some reader programs may ignore x and y. A safe default for writing an ILBM 
is (x, y) = (0, 0). 


The number of source bitplanes in the BODY chunk is stored in nPlanes. AnILBM witha CMAP 
but no BODY and nPlanes = 0 is the recommended way to store a color map. 


Note: Color numbers are color map index values formed by pixels in the destination bitmap, which 
may be deeper than nPlanes if a DEST chunk calls for merging the image into a deeper image. 


The field masking indicates what kind of masking is to be used for this image. The value mskNone 
designates an opaque rectangular image. The value mskHasMask means that a mask plane is inter- 
leaved with the bitplanes in the BODY chunk (see below). The value mskHasTransparentColor 
indicates that pixels in the source planes matching t ransparentColorare to be considered "trans- 
parent”. (Actually, transparentColor isn’t a "color number" since it’s matched with numbers 
formed by the source bitmap rather than the possibly deeper destination bitmap. Note that having 


382 Amiga ROM Kernel Reference Manual: Devices 


a transparent color implies ignoring one of the color registers. The value mskLasso indicates the 
reader may construct a mask by lassoing the image as in MacPaint™. To do this, put a 1 pixel 
border of transparentColor around the image rectangle. Then do a seed fill from this border. 
Filled pixels are to be transparent. 


Issue: Include in an appendix an algorithm for converting a transparent color to a mask plane, and 
maybe a lasso algorithm. 


A code indicating the kind of data compression used is stored in compression. Beware that using 
data compression makes your data unreadable by programs that don’t implement the matching 
decompression algorithm. So we’ll employ as few compression encodings as possible. The run 
encoding byteRun1 is documented in Appendix C. 


The field padi is a pad byte reserved for future use. It must be set to 0 for consistency. 


The transparentColor specifies which bit pattern means "transparent". This only applies if 
masking is mskHasTransparentColor ormskLasso. Otherwise, transparentColor should 
be 0 (see above). 


The pixel aspect ratio is stored as a ratio in the two fields xAspect and yAspect. This may be 
used by programs to compensate for different aspects or to help interpret the fields w, h, x, y, 
pageWidth, and pageHeight, which are in units of pixels. The fraction xAspect/yAspect 
represents a pixel’s width/height. It’s recommended that your programs store proper fractions in 
the BitmapHeader, but aspect ratios can always be correctly compared with the test: 


xAspect * yDesiredAspect = yAspect * xDesiredAspect 
Typical values for aspect ratio are width : height = 10: 11 for an Amiga 320 x 200 display and 1 : 
1 for a Macintosh™ display. 


The size in pixels of the source "page" (any raster device) is stored in pageWidth and pageHeight, 
e.g., (320, 200) for a low resolution Amiga display. This information might be used to scale an 
image or to automatically set the display format to suit the image. Note that the image can be larger 
than the page. 


CMAP 


The optional (but encouraged) property "CMAP" stores color map data as triplets of red, green, and 
blue intensity values. The n color map entries ("color registers") are stored in the order 0 through 
n-1, totaling 3n bytes. Thus n is the ckSize/3. Normally, n would equal 2°”, 


A CMAP chunk contains a ColorMap array as defined below. Note that these typedefs assume a C 
compiler that implements packed arrays of 3-byte elements. 


typedef struct { 


UBYTE red, green, blue; /* color intensities 0..255 */ 
} ColorRegister; /* size = 3 bytes */ 
typedef ColorRegister ColorMap[n]; /* size = 3n bytes */ 


The color components red, green, and blue are each stored as a byte (8 bits) representing frac- 
tional intensity values expressed in 256ths in the range 0 through 255 (e.g., 24/256). White is 
(255,255,255—i.e., hex OxFFOxFF,OxFF) and black is (0,0,0). If your machine has less color 
resolution, use the higher order color bits when displaying by simply shifting the CMAP R, G, and 
B values to the right. When writing a CMAP, storage of less than 8 bits each of R, G, and B was 


IFF Specification: LBM 383 


previously accomplished by left justifying the significant bits within the stored bytes (i.e., a 4-bit 
per gun value of OxF,OxF,OxF was stored as OxF0,0xF0,0xFO). This provided correct color values 
when the ILBM was redisplayed on the same hardware since the zeros were shifted back out. 


However, if color values stored by the above method were used as-is when redisplaying on 
hardware with more color resolution, diminished color could result. For example, a value of 
(OxFO,0xF0,0xF0) would be pure white on 4-bit-per-gun hardware (i.e., OxF,OxF,OxF), but not quite 
white (OxF0,0xF0,0xF0) on 8-bit-per-gun hardware. 


Therefore, when storing CMAP values, it is now suggested that you store full 8 bit values for R, 
G, and B which correctly scale your color values for eight bits. For 4-bit RGB values, this can be 
as simple as duplicating the 4-bit values in both the upper and lower parts of the bytes—i.e., store 
(0x1,0x7,0xF) as (0x11,0x77,0xFF). This will provide a more correct color rendition if the image 
is displayed on a device with 8 bits per gun. 


When reading in a CMAP for 8-bit-per-gun display or manipulation, you may want to assume that 
any CMAP which has 0 values for the low bits of all guns for all registers was stored shifted rather 
than scaled, and provide your own scaling. Use defaults if the color map is absent or has fewer 
color registers than you need. Ignore any extra color registers. 


The example type Color4 represents the format of a color register in working memory of an Amiga 
computer, which has 4 bit video DACs. (The ": 4" tells smarter C compilers to pack the field into 4 
bits.) 


typedef struct { 
unsigned padl :4, red :4, green :4, blue :4; 
} Color4; /* Amiga RAM format. Not filed. */ 


Remember that every chunk must be padded to an even length, so a color map with an odd number 
of entries would be followed by a 0 byte, not included in the ckSize. 
Storing 24-bit ILBMs Information on storing 24-bit ILBMs can be found in the appendix 
of this section. 
GRAB 


The optional property "GRAB" locates a "handle" or "hotspot" of the image relative to its upper left 
comer, e.g., when used as a mouse cursor or a "paint brush". A GRAB chunk contains a Point 2D. 


typedef struct { 
WORD x, y; /* relative coordinates (pixels) */ 
} Point2D; 


DEST 


The optional property "DEST" is a way to say how to scatter zero or more source bitplanes into a 
deeper destination image. Some readers may ignore DEST. 


The contents of a DEST chunk is Destmerge structure: 


typedef struct { 


UBYTE depth; /* # bitplanes in the original source */ 
UBYTE padl; /* unused; for consistency put 0 here */ 
UWORD planePick; /* how to scatter source bitplanes into destination */ 
UWORD planeOnOff; /* default bitplane data for planePick */ 
UWORD planeMask; /* selects which bitplanes to store into */ 


} Destmerge; 


384 Amiga ROM Kernel Reference Manual: Devices 


The low order depth number of bits in planePick, planeOnOff, and planeMask correspond 
one-to-one with destination bitplanes. Bit 0 with bitplane 0, etc. (Any higher order bits should 
be ignored.) "1" bits in planePick mean "put the next source bitplane into this bitplane", so 
the number of "1" bits should equal nPlanes. "OQ" bits mean “put the corresponding bit from 
planeOnOff into this bitplane". Bits in planeMask gate writing to the destination bitplane: "1" 
bits mean "write to this bitplane” while "0" bits mean "leave this bitplane alone". The normal case 
(with no DEST property) is equivalent to planePick = planeMask = 2°Plnes _ 4, 


Remember that color numbers are formed by pixels in the destination bitmap (depth planes deep) 
not in the source bitmap (nPlanes planes deep). 


SPRT 


The presence of an "SPRT" chunk indicates that this image is intended as a sprite. It’s up to the 
reader program to actually make it a sprite, if even possible, and to use or overrule the sprite 
precedence data inside the SPRT chunk: 


typedef UWORD SpritePrecedence; /* relative precedence, 0 is the highest */ 


Precedence 0 is the highest, denoting a sprite that is foremost. 


Creating a sprite may imply other setup. E.g., a 2 plane Amiga sprite would have transparent- 
Color =0. Color registers 1, 2, and 3 in the CMAP would be stored into the correct hardware 
color registers for the hardware sprite number used, while CMAP color register 0 would be ignored. 


CAMG 


A "CAMG" chunk is specifically for Commodore Amiga ILBMs. All Amiga-based reader and 
writer software should deal with CAMG. The Amiga supports many different video display modes 
including interlace, Extra Halfbrite, hold and modify (HAM), plus a variety of new modes under 
the 2.0 operating system. A CAMG chunk contains a single long word (length=4) which specifies 
the Amiga display mode of the picture. 


Prior to 2.0, it was possible to express all available Amiga ViewModes in 16 bits of flags 
(Viewport->Modes or NewScreen->ViewModes). Old-style writers and readers place a 16- 
bit Amiga ViewModes value in the low word of the CAMG, and zeros in the high word. The 
following Viewmode flags should always be removed from old-style 16-bit viewModes values 
when writing or reading them: 


EXTENDED_MODE | SPRITES | VP_HIDE | GENLOCK AUDIO | GENLOCK_VIDEO (=0x7102, mask=0x8EFD) 


New ILBM readers and writers, should treat the full CAMG longword as a 32-bit ModeID to support 
new and future display modes. 


New ILBM writers, when running under the 2.0 Amiga operating system, should directly store the 
full 32-bit return value of the graphics function Get VPModeID (vp) inthe CAMG longword. When 
running under 1.3, store a 16-bit viewmodes value masked as described above. 


ILBM readers should only mask bits out of a CAMG if the CAMG has a zero upper word (see 
exception below). New ILBM readers, when running under 2.0, should then treat the 32-bit CAMG 
value as a ModeID, and should use the graphics ModeNotAvailable() function to determine if 
the mode is available. If the mode is not available, fall back to another suitable display mode. When 
running under 1.3, the low word of the CAMG may generally be used to open a compatible display. 


IFF Specification: ILBM 385 


Note that one popular graphics package stores garbage in the upper word of the CAMG of brushes, 
and incorrect values (generally zero) in the low word. You can screen for such garbage values by 
testing for non-zero in the upper word of a ModeID in conjunction with the 0x00001000 bit NOT 
set in the low word. 


The following code fragment demonstrates ILBM reader filtering of inappropriate bits in 16-bit 
CAMG values. 


#include <graphics/view.h> 
#include <graphics/displayinfo.h> 


/* Knock bad bits out of old-style CAMG modes before checking availability. 
* (some ILBM CAMG’s have these bits set in old 1.3 modes, and should not) 
* If not an extended monitor ID, or if marked as extended but missing 
* upper 16 bits, screen out inappropriate bits now. 

*/ 
if((!(modeid & MONITOR _ID MASK)) || 
((modeid & EXTENDED MODE) &&(!(modeid & OxFFFF0000)))) 
modeid &= 
(~ (EXTENDED _MODE|SPRITES|GENLOCK AUDIO|GENLOCK VIDEO|VP_HIDE)); 


/* Check for bogus CAMG like some brushes have, with junk in 
* upper word and extended bit NOT set not set in lower word. 
*/ 

if((modeid & OxFFFF0000)&&(! (modeid & EXTENDED MODE) ) ) 

{ 


/* Bad CAMG, so ignore CAMG and determine a mode based on 
* based on pagesize or aspect 

*/ 

modeid = NULL; 

if(wide >= 640) modeid |= HIRES; 

if(high >= 400) modeid |= LACE; 

} 


Now, ModeNotAvailable() may be used to determine if the mode is available. 


If the mode is not available, you may prompt the user for a mode 
choice, or search the 2.0 display database for an appropriate 
replacement. mode, or you may be able to get a relatively compatible 
old display mode by masking out all bits except 

HIRES | LACE | HAM | EXTRA_HALFBRITE 


% OF OF OF OF Ob OF OF 


386 Amiga ROM Kernel Reference Manual: Devices 


3. Standard "BODY" Data Chunk 
Raster Layout 


Raster scan proceeds left-to-right (increasing X) across scan lines, then top-to-bottom (increasing 
Y) down columns of scan lines. The coordinate system is in units of pixels, where (0,0) is the upper 
left comer. 


The raster is typically organized as bitplanes in memory. The corresponding bits from each plane, 
taken together, make up an index into the color map which gives a color value for that pixel. The 
first bitplane, plane 0, is the low order bit of these color indexes. 


A scan line is made of one "row" from each bitplane. A row is one plane’s bits for one scan line, 
but padded out to a word (2 byte) boundary (not necessarily the first word boundary). Within each 
row, successive bytes are displayed in order and the most significant bit of each byte is displayed 
first. 


A "mask" is an optional "plane" of data the same size (w, h) as a bitplane. It tells how to "cut 
out" part of the image when painting it onto another image. "One" bits in the mask mean "copy the 
corresponding pixel to the destination". "Zero" mask bits mean "leave this destination pixel alone”. 
In other words, "zero" bits designate transparent pixels. 


The rows of the different bitplanes and mask are interleaved in the file (see below). This localizes 
all the information pertinent to each scan line. It makes it much easier to transform the data while 
reading it to adjust the image size or depth. It also makes it possible to scroll a big image by 
swapping rows directly from the file without the need for random-access to all the bitplanes. 


BODY 


The source raster is stored ina "BODY" chunk. This one chunk holds all bitplanes and the optional 
mask, interleaved by row. 


The BitMapHeader, in a BMHD property chunk, specifies the raster’s dimensions w, h, and 
nPlanes. It also holds the masking field which indicates if there is a mask plane and the 
compression field which indicates the compression algorithm used. This information is needed 
to interpret the BODY chunk, so the BMHD chunk must appear first. While reading an ILBM’s 
BODY, a program may convert the image to another size by filling (with transparentColor) or 
clipping. 

The BODY’s content is a concatenation of scan lines. Each scan line is a concatenation of one 
row of data from each plane in order 0 through nPlanes-1 followed by one row from the mask 
(if masking = hasMask). If the BitMapHeader field compression is cmpNone, all h rows are 
exactly (w+15) /16 words wide. Otherwise, every row is compressed according to the specified 
algorithm and the stored widths depend on the data compression. 


Reader programs that require fewer bitplanes than appear in a particular ILBM file can combine 
planes or drop the high-order (later) planes. Similarly, they may add bitplanes and/or discard the 
mask plane. 


Do not compress across rows, and don’t forget to compress the mask just like the bitplanes. 
Remember to pad any BODY chunk that contains an odd number of bytes and skip the pad when 
reading. 


IFF Specification: ILBM 387 


4. Nonstandard Data Chunks 


The following data chunks were defined after various programs began using FORM ILBM so 
they are "nonstandard" chunks. See the registry document for the latest information on additional 
non-standard chunks. 


CRNG 


A "CRNG" chunk contains "color register range” information. It’s used by Electronic Arts’ Deluxe 
Paint program to identify a contiguous range of color registers for a "shade range” and color cycling. 
There can be zero or more CRNG chunks in an ILBM, but all should appear before the BODY 
chunk. Deluxe Paint normally writes 4 CRNG chunks in an ILBM when the user asks it to "Save 
Picture". 


typedef struct { 


WORD padi; /* reserved for future use; store 0 here x/ 
WORD rate; /* color cycle rate */ 
WORD flags; /* see below */ 
UBYTE low, high; /* lower and upper color registers selected */ 
} CRange; 


The bits of the £1ags word are interpreted as follows: if the low bit is set then the cycle is "active", 
and if this bit is clear it is not active. Normally, color cycling is done so that colors move to the 
next higher position in the cycle, with the color in the high slot moving around to the low slot. If 
the second bit of the flags word is set, the cycle moves in the opposite direction. As usual, the other 
bits of the flags word are reserved for future expansion. Here are the masks to test these bits: 


#define RNG ACTIVE 1 
#define RNG REVERSE 2 


The fields low and high indicate the range of color registers (color numbers) selected by this 
CRange. 
The field active indicates whether color cycling is on or off. Zero means off. 


The field rate determines the speed at which the colors will step when color cycling is on. The 
units are such that a rate of 60 steps per second is represented as 2'* = 16384. Slower rates can be 
obtained by linear scaling: for 30 steps/second, rate = 8192; for 1 step/second, rate = 16384/60 ~ 
213s 


Warning! One popular paint package always sets the RNG_ACTIVE bit, but uses a rate 
of 36 (decimal) to indicate cycling is not active. 


CCRT 


Commodore’s Graphicraft program uses a similar chunk "CCRT" (for Color Cycling Range and 
Timing). This chunk contains a CycleInfo structure. 


typedef struct { 


WORD direction; /* 0 = don’t cycle. 1 = cycle forwards */ 

/* (1, 2, 3). -1 = cycle backwards (3, 2, 1) */ 
UBYTE start, end; /* lower and upper color registers selected */ 
LONG seconds; /* # seconds between changing colors plus... */ 
LONG microseconds; /* # microseconds between changing colors «/ 
WORD pad; /* reserved for future use; store 0 here */ 
} CycleInfo; 


This is very similar to a CRNG chunk. A program would probably only use one of these two 
methods of expressing color cycle data, new programs should use CRNG. You could write out both 
if you want to communicate this information to both Deluxe Paint and Graphicraft. 


388 Amiga ROM Kernel Reference Manual: Devices 


Appendix A. ILBM Regular Expression 


Here’s a regular expression summary of the FORM ILBM syntax. This could be an IFF file or a 
part of one. 


ILBM ::= "FORM" #{ "ILBM" BMHD [CMAP] [GRAB] [DEST] [SPRT] [CAMG] 
CRNG* CCRT* [BODY] } 

BMHD ::= "BMHD" #{ BitMapHeader } 

CMAP ::= "CMAP" #{ (red green blue) * } [0] 

GRAB ::= "GRAB" #{ Point2D } 

DEST ::= "DEST" #{ DestMerge } 

SPRT ::= "SPRT" #{ SpritePrecedence } 

CAMG ::= "CAMG" #{ LONG 

CRNG ::= "CRNG" #{ CRange } 

CCRT ::= "CCRT" #{ CycleInfo } 

BODY ::= "BODY" #{ UBYTE* } (0) 


The token "#" represents ackSize LONG count of the following braced data bytes. E.g.,a BMHD’s 
"#" should equal sizeof (BitMapHeader). Literal strings are shown in "quotes", [square bracket 
items] are optional, and "*" means 0 or more repetitions. A sometimes-needed pad byte is shown 
as w [0] m 

The property chunks BMHD, CMAP, GRAB, DEST, SPRT, CAMG and any CRNG and CCRT 
data chunks may actually be in any order but all must appear before the BODY chunk since ILBM 
readers usually stop as soon as they read the BODY. If any of the 6 property chunks are missing, 
default values are inherited from any shared properties (if the ILBM appears inside an IFF LIST 
with PROPs) or from the reader program’s defaults. If any property appears more than once, the 
last occurrence before the BODY is the one that counts since that’s the one that modifies the BODY. 


Appendix B. ILBM Box Diagram 


Here is a box diagram for a simple example: an uncompressed image 320 x 200 pixels x 3 bitplanes. 
The text to the right of the diagram shows the outline that would be printed by the Sift utility 
program for this particular file. 


FORM 24070 ILBM 


‘ILBM’ 
‘BMHD’ 
320, 200, 0, 0, 3, 0, 0, 0... BMHD 20 
‘CMAP’ 21 
0, 0, 0; 32, 0, 0; 64, 0, 0... -CMAP 21 
.BODY 24000 





The "0" after the CMAP chunk is a pad byte. 


IFF Specification: ILBM 389 


Appendix C. IFF Hints 


Hints on ILBM files from Jerry Morrison, Oct 1988. How to avoid some pitfalls when reading 
ILBM files: 


e Don’t ignore the BitMapHeader.masking field. A bitmap with a mask (such as a partially- 
transparent DPaint brush or a DPaint picture with a stencil) will read as garbage if you don’t 
de-interleave the mask. 


e Don’t assume all images are compressed. Narrow images aren’t usually run-compressed since 
that would actually make them longer. 


e Don’t assume a particular image size. You may encounter overscan pictures and PAL pictures. 


Different hardware display devices have different color resolutions: 


Device R:G:B bits maxColor 
Mac SE 1 1 
IBM EGA 2:2:2 3 
Atari ST 32353 7 
Amiga 4:4:4 15 
CD-I 5:5:5 31 
IBM VGA 6:6:6 63 
Mac II 8:8:8 255 


An ILBM CMAP defines 8 bits of Red, Green and Blue (i.e., 8:8:8 bits of R:G:B). When displaying 
on hardware which has less color resolution, just take the high order bits. For example, to convert 
ILBM’s 8-bit Red to the Amiga’s 4-bit Red, right shift the data by 4 bits (R4 := R8 >> 4). 


To convert hardware colors to ILBM colors, the ILBM specification says just set the high bits (R8 
:= R4 << 4). But you can transmit higher contrast to foreign display devices by scaling the data 
[0..maxColor] to the full range [0..255]. In other words, R8 := (Rn x 255) ? maxColor. (Example 
#1: EGA color 1:2:3 scales to 85:170:255. Example #2: Amiga 15:7:0 scales to 255:119:0). This 
makes a big difference where maxColor is less than 15. In the extreme case, Mac SE white (1) 
should be converted to ILBM white (255), not to ILBM gray (128). 


CGA and EGA subtleties 


IBM EGA colors in 350 scan line mode are 2:2:2 bits of R:G:B, stored in memory as xxR’G’B’RBG. 
That’s 3 low-order bits followed by 3 high-order bits. 


IBM CGA colors are 4 bits stored in a byte as xxxxIRGB. (EGA colors in 200 scan line modes are 
the same as CGA colors, but stored in memory as xxxIxRGB.) That’s 3 high-order bits (one for each 
of R, G, and B) plus one low-order " Intensity” bit for all 3 components R, G, and B. Exception: 
IBM monitors show IRGB = 0110 as brown, which is really the EGA color R:G:B = 2:1:0, not dark 
yellow 2:2:0. 


24-bit ILBMs 


When storing deep images as ILBMs (e.g., images with 8 bits each of R,G, and B), the bits for each 
pixel represent an absolute RGB value for that pixel rather than an index into a limited color map. 
The order for saving the bits is critical since a deep ILBM would not contain the usual CMAP of 
RGB values (such a CMAP would be too large and redundant). 


390 Amiga ROM Kernel Reference Manual: Devices 


To interpret these "deep" ILBMs, it is necessary to have a standard order in which the bits of the 
R, G, and B values will be stored. A number of different orderings have already been used in deep 
ILBMs and a default has been chosen from them. 


The following bit ordering has been chosen as the default bit ordering for deep ILBMs. 


Default standard deep ILBM bit ordering: 
saved first saved last 
RO R1 R2 R3 R4 RS R6 R7 GO G1 G2 G3 G4 G5 G6 G7 BO B1 B2 B3 B4 BS B6 B7 


One other existing deep bit ordering that you may encounter is the 21-bit NewTek format. 


NewTek deep ILBM bit ordering: 
saved first saved last 
R7 G7 B7 R6 G6 B6 RS GS BS R4 G4 B4 R3 G3 B3 R2 G2 B2 R1 G1 B1 RO GO BO 


Note that you may encounter CLUT chunks in deep ILBMs. See the Third Party Specs appendix 
for more information on CLUT chunks. 








Appendix D. ByteRun1 Run Encoding 


The run encoding scheme byteRun1 is best described by pseudo code for the decoder Unpacker 
(called UnPackBits in the Macintosh™ toolbox): 


UnPacker: 
LOOP until produced the desired number of bytes 
Read the next source byte into n 
SELECT n FROM 


(0..127] => copy the next n+l bytes literally 
{[-1..-127] => replicate the next byte -ntl times 
-128 => no operation 
ENDCASE; 

ENDLOOP; 


In the inverse routine Packer, it’s best to encode a 2 byte repeat run as a replicate run except when 
preceded and followed by a literal run, in which case it’s best to merge the three into one literal run. 
Always encode 3 byte repeats as replicate runs. 


Remember that each row of each scan line of a raster is separately packed. 


Appendix E. Standards Committee 
The following people contributed to the design of this FORM ILBM standard: 


Bob "Kodiak" Bums, Commodore-Amiga 
R. J. Mical, Commodore-Amiga 

Jerry Morrison, Electronic Arts 

Greg Riker, Electronic Arts 

Steve Shaw, Electronic Arts 

Dan Silva, Electronic Arts 

Barry Walsh, Commodore-Amiga 


IFF Specification: ILBM 391 


"FTXT" IFF Formatted Text 


Date: November 15, 1985 (Updated Oct, 1988 Commodore-Amiga, Inc.) 
From: — Steve Shaw and Jerry Morrison, Electronic Arts and Bob "Kodiak" Burns, Commodore-Amiga 
Status: Adopted 


1. Introduction 


This memo is the IFF supplement for FORM FTXT. An FTXT is an IFF "data section" or "FORM 
type"—which can be an IFF file or a part of one—containing a stream of text plus optional formatting 
information."EA IFF 85" is Electronic Arts’ standard for interchange format files. (See the IFF 
reference.) 


An FYXT is an archival and interchange representation designed for three uses. The simplest use 
is for a "console device" or "glass teletype” (the minimal 2-D text layout means): a stream of 
"graphic" ("printable") characters plus positioning characters "space" ("SP") and line terminator 
("LF"). This is not intended for cursor movements on a screen although it does not conflict with 
standard cursor-moving characters. The second use is text that has explicit formatting information 
(or "looks") such as font family and size, typeface, etc. The third use is as the lowest layer of a 
structured document that also has "inherited" styles to implicitly control character looks. For that 
use, FORMs FTXT would be embedded within a future document FORM type. The beauty of 
FTXT is that these three uses are interchangeable, that is, a program written for one purpose can 
read and write the others’ files. So a word processor does not have to write a separate plain text file 
to communicate with other programs. 


Text is stored in one or more "CHRS" chunks inside an FTXT. Each CHRS contains a stream of 
8-bit text compatible with ISO and ANSI data interchange standards. FTXT uses just the central 
character set from the ISO/ANSI standards. (These two standards are henceforth called "ISO/ANSI" 
as in "see the ISO/ANSI reference".) 


Since it’s possible to extract just the text portions from future document FORM types, programs 
can exchange data without having to save both plain text and formatted text representations. 


Character looks are stored as embedded control sequences within CHRS chunks. This document 
specifies which class of control sequences to use: the CSI group. This document does not yet 
specify their meanings, e.g., which one means "tum on italic face". Consult ISO/ANSI. 


Section 2 defines the chunk types character stream "CHRS" and font specifier "FONS". These are 
the "standard" chunks. Specialized chunks for private or future needs can be added later. Section 3 
outlines an FTXT reader program that strips a document down to plain unformatted text. Appendix 
A is a code table for the 8-bit ISO/ANSI character set used here. Appendix B is an example FTXT 
shown as a box diagram. Appendix C is a racetrack diagram of the syntax of ISO/ANSI control 
sequences. 


Reference: 


Amiga® is a registered trademark of Commodore-Amiga, Inc. Electronic Arts™ is a trademark of 
Electronic Arts. 


all IFF files. 





IFF Specification: FTXT 393 


ISO/ANSI: ISO/DIS 6429.2 and ANSI X3.64-1979. International Organization for Standardization 
(ISO) and American National Standards Institute (ANSI) data-interchange standards. The relevant 
parts of these two standards documents are identical. ISO standard 2022 is also relevant. 


2. Standard Data and Property Chunks 


The main contents of aFORM FTXT is inits character stream "CHRS" chunks. Formatting property 
chunks may also appear. The only formatting property yet defined is "FONS", a font specifier. A 
FORM FTXT with no CHRS represents an empty text stream. A FORM FTXT may contain nested 
IFF FORMs, LISTs, or CATs, although a "stripping" reader (see section 3) will ignore them. 


Character Set 


FORM FTXT uses the core of the 8-bit character set defined by the ISO/ANSI standards cited at 
the start of this document. (See Appendix A for a character code table.) This character set is 
divided into two "graphic" groups plus two "control" groups. Eight of the control characters begin 
ISO/ANSI standard control sequences. (See "Control Sequences" below.) Most control sequences 
and control characters are reserved for future use and for compatibility with ISO/ANSI. Current 
reader programs should skip them. 


e CO is the group of control characters in the range NUL (hex 0) through hex 1F. Of these, only 
LF (hex 0A) and ESC (hex 1B) are significant. ESC begins a control sequence. LF is the line 
terminator, meaning "go to the first horizontal position of the next line". All other CO characters 
are not used. In particular, CR (hex OD) is not recognized as a line terminator. 


GO is the group of graphic characters in the range hex 20 through hex 7F. SP (hex 20) is the 
space character. DEL (hex 7F) is the delete character which is not used. The rest are the 
standard ASCII printable characters "!" (hex 21) through "™ (hex 7E). 


C1 is the group of extended control characters in the range hex 80 through hex 9F. Some of 
these begin control sequences. The control sequence starting with CSI (hex 9B) is used for 
FTXT formatting. All other control sequences and C1 control characters are unused. 


e 


e 


e G1 is the group of extended graphic characters in the range NBSP (hex AO) through "y" (hex 
FF). It is one of the alternate graphic groups proposed for ISO/ANSI standardization. 


Control Sequences 


Eight of the control characters begin ISO/ANSI standard "control sequences" (or "escape se- 
quences"). These sequences are described below and diagramed in Appendix C. 


GO ::= (SP through DEL) 
G1 (NBSP through "y") 


ESC-Seq 


: ESC (SP through "/") * ("0" through "~") 
ShiftToG2 : 


:= SS2 GO 
ShiftToG3 ::= SS3 GO 
CSI-Seq := CSI (SP through "?") * ("@" through """) 
DCS-Seq := (DCS | OSC | PM | APC) (SP through "~" | Gl) * ST 


394 Amiga ROM Kernel Reference Manual: Devices 


"ESC-Seq" is the control sequence ESC (hex 1B), followed by zero or more characters in the range 
SP through "/" (hex 20 through hex 2F), followed by a character in the range "0" through "“" (hex 
30 through hex 7E). These sequences are reserved for future use and should be skipped by current 
FYXT reader programs. 


SS2 (hex 8E) and SS3 (hex 8F) shift the single following GO character into yet-to-be-defined graphic 
sets G2 and G3, respectively. These sequences should not be used until the character sets G2 and 
G3 are standardized. A reader may simply skip the SS2 or SS3 (taking the following character as 
a corresponding GO character) or replace the two-character sequence with a character like "?" to 
mean "absent". 


FTXT uses "CSI-Seq" control sequences to store character formatting (font selection by number, 
type face, and text size) and perhaps layout information (position and rotation). "CSI-Seq" control 
sequences start with CSI (the "control sequence introducer", hex 9B). Syntactically, the sequence 
includes zero or more characters in the range SP through "?" (hex 20 through hex 3F) and a 
concluding character in the range "@" through "~" (hex 40 through hex 7E). These sequences may 
be skipped by a minimal FTXT reader, i.e., one that ignores formatting information. 


Note: A future FTXT standardization document will explain the uses of CSI-Seq sequences for 
setting character face (light weight vs. medium vs. bold, italic vs. upright, height, pitch, position, 
and rotation). For now, consult the ISO/ANSI references. 


"DCS-Seq" is the control sequences starting with DCS (hex 90), OSC (hex 9D), PM (hex 9E), or 
APC (hex 9F), followed by zero or more characters each of which is in the range SP through "™ 
(hex 20 through hex 7E) or else a G1 character, and terminated by an ST (hex 9C). These sequences 
are reserved for future use and should be skipped by current FTXT reader programs. 


Data Chunk CHRS 


A CHRS chunk contains a sequence of 8-bit characters abiding by the ISO/ANSI standards cited at 
the start of this document. This includes the character set and control sequences as described above 
and summarized in Appendix A and C. 


A FORM FTXT may contain any number of CHRS chunks. Taken together, they represent a single 
stream of textual information. That is, the contents of CHRS chunks are effectively concatenated 
except that (1) each control sequence must be completely within a single CHRS chunk, and (2) 
any formatting property chunks appearing between two CHRS chunks affects the formatting of the 
latter chunk’s text. Any formatting settings set by control sequences inside a CHRS carry over to 
the next CHRS in the same FORM FTXT. All formatting properties stop at the end of the FORM 
since IFF specifies that adjacent FORMs are independent of each other (although not independent 
of any properties inherited from an enclosing LIST or FORM). 


Property Chunk FONS 


The optional property "FONS" holds a FontSpecifier as defined in the C declaration below. It assigns 
a font to a numbered "font register" so it can be referenced by number within subsequent CHRS 
chunks. (This function is not provided within the ISO and ANSI standards.) The font specifier 
gives both a name and a description for the font so the recipient program can do font substitution. 


IFF Specification: FTXT 395 


By default, CHRS text uses font 1 until it selects another font. A minimal text reader always uses 
font 1. If font 1 hasn’t been specified, the reader may use the local system font as font 1. 


typedef struct { 
UBYTE id; /* 0 through 9 is a font id number referenced by an SGR 
control sequence selective parameter of 10 through 19. 
Other values are reserved for future standardization. */ 


UBYTE padl; /* reserved for future use; store 0 here x/ 
UBYTE proportional; /* proportional font-- O=unknown, 1l=no, 2=yes */ 
UBYTE serif; /* serif font-- 0 = unknown, 1 = no, 2 = yes x/ 
char name[]; /* A NUL-terminated string naming the preferred font. x/ 


} FontSpecifier; 


Fields are filed in the order shown. The UBYTE fields are byte-packed (2 per 16-bit word). The 
field padi is reserved for future standardization. Programs should store 0 there for now. 


The field proportional indicates if the desired font is proportional width as opposed to fixed 
width. The field serif indicates if the desired font is serif as opposed to sans serif. Issue: Discuss 
font substitution! 


Future Properties 


New optional property chunks may be defined in the future to store additional formatting information. 
They will be used to represent formatting not encoded in standard ISO/ANSI control sequences and 
for "inherited" formatting in structured documents. Text orientation might be one example. 


Positioning Units 


Unless otherwise specified, position and size units used in FTXT formatting properties and control 
sequences are in decipoints (720 decipoints/inch). This is ANSI/ISO Positioning Unit Mode (PUM) 
2. While a metric standard might be nice, decipoints allow the existing U.S.A. typographic units to 
be encoded easily, e.g., "12 points” is "120 decipoints”. 


3. FT XT Stripper 


An FYXT reader program can read the text and ignore all formatting and structural information in a 
document FORM that uses FORMs FTXT for the leaf nodes. This amounts to stripping a document 
down to a stream of plain text. It would do this by skipping over all chunks except FTXT.CHRS 
(CHRS chunks found inside a FORM FTXT) and within the FTXT.CHRS chunks skipping all 
control characters and control sequences. (Appendix C diagrams this text scanner.) It may also 
read FTXT.FONS chunks to find a description for font 1. 


396 Amiga ROM Kernel Reference Manual: Devices 


LSN 


Appendix A: Character Code Table 


This table corresponds to the ISO/DIS 6429.2 and ANSI X3.64-1979 8-bit character set standards. 
Only the core character set of those standards is used in FTXT. 


Two G1 characters aren’t defined in the standards and are shown as dark gray entries in this table. 
Light gray shading denotes control characters. (DEL is a control character although it belongs to 
the graphic group G0.) 

ISO / DIS 6429.2 and ANSI X3.64-1979 Character Code Table 


MSN (most significant nibble) 









5 cacs| ooo 
eter . oo o]o a mem mma 


‘@=z 4 az "© 
K 


se00[e>oe[saus[onro] | 


a 











Vp \ _y yy 
Control Graphic group GO Control Graphic group 
group CO group Cl Gl 


NBSP is a non-breaking space 
SHY isa soft hyphen 


IFF Specification: FTXT 397 


Appendix B. FTXT Example 


Here’s a box diagram for a simple example: "The quick brown fox jumped. Four score and seven", 
written in a proportional serif font named "Roman". 


‘FONS’ 
01, 00, 02, 02 


86 
‘CHRS’ 27 


The quick brown fox jumped. 


‘CHRS! 20 


Four score and seven 





The "0" after the first CHRS chunk is a pad byte. 


398 Amiga ROM Kernel Reference Manual: Devices 





Appendix C. ISO/ANSI Control Sequences 


This is a racetrack diagram of the ISO/ANSI characters and control sequences as used in 
FTXT.CHRS chunks. 


line terminator F 


E 


ESC-Seq 

SP through (1) 
printable SP through (~) ref 

hii 2 
ShiftToG. rSS2 Go, (produces a G2 character) 
ShiftToG3 Ss3 | (produces a G3 character) 
/- 

CSrSeq —— J) (@) through (~) 

SP through () 
DCS-Seq DCS, OSC, PM, or APC | —-_———______~ 

[SP through (?) | 
discard 
any other character 


Of the various control sequences, only CSI-Seq is used for FTXT character formatting information. 
The others are reserved for future use and for compatibility with ISO/ANSI standards. Certain 
character sequences are syntactically malformed, e.g., CSI followed by a CO, C1, or G1 character. 
Writer programs should not generate reserved or malformed sequences and reader programs should 
skip them. 


Consult the ISO/ANSI standards for the meaning of the CSI-Seq control sequences. 


The two character set shifts SS2 and SS3 may be used when the graphic character groups G2 and 
G3 become standardized. 


IFF Specification: FTXT 399 


"SMUS" IFF Simple Musical Score 


Date: February 20, 1987 (SID —Clef and SID_Tempo added Oct, 1988) 
From: Jerry Morrison, Electronic Arts 
Status: Adopted 


1. Introduction 


This is a reference manual for the data interchange format "SMUS", which stands for Simple 
MUsical Score. "EA IFF 85" is Electronic Arts’ standard for interchange format files. A FORM 
or "data section") such as FORM SMUS can be an IFF file or a part of one. [See "EA IFF 85" 
Electronic Arts Interchange File Format.] 


SMUS is a practical data format for uses like moving limited scores between programs and storing 
theme songs for game programs. The format should be geared for easy read-in and playback. So 
FORM SMUS uses the compact time encoding of Common Music Notation (half notes, dotted 
quarter rests, etc.). The SMUS format should also be structurally simple. So it has no provisions 
for fancy notational information needed by graphical score editors or the more general timing 
(overlapping notes, etc.) and continuous data (pitch bends, etc.) needed by performance-oriented 
MIDI recorders and sequencers. Complex music programs may wish to save in a more complete 
format, but still import and export SMUS when requested. 


A SMUS score can say which "instruments" are supposed play which notes. But the score is 
independent of whatever output device and driver software is used to perform the notes. The score 
can contain device- and driver-dependent instrument data, but this is just a cache. As long as a 
SMUS file stays in one environment, the embedded instrument data is very convenient. When you 
move a SMUS file between programs or hardware configurations, the contents of this cache usually 
become useless. 


Like all IFF formats, SMUS is a filed or "archive" format. It is completely independent of score 
representations in working memory, editing operations, user interface, display graphics, computation 
hardware, and sound hardware. Like all IFF formats, SMUS is extensible. 


SMUS is not an end-all musical score format. Other formats may be more appropriate for certain 
uses. (We'd like to design an general-use IFF score format "GSCR". FORM GSCR would encode 
fancy notational data and performance data. There would be a SMUS to/from GSCR converter.) 


Section 2 gives important background information. Section 3 details the SMUS components by 
defining the required property score header "SHDR", the optional text properties name "NAME", 
copyright "(c) ", and author "AUTH", optional text annotation "ANNO", the optional instrument 
specifier "INS1", and the track data chunk "TRAK". Section 4 defines some chunks for particular 
programs to store private information. These are "standard" chunks; specialized chunks for future 
needs can be added later. Appendix A is a quick-reference summary. Appendix B is an example 
box diagram. Appendix C names the committee responsible for this standard. 


References: 


IFF files. 

"8SVX" IFF 8-Bit Sampled Voice documents a data format for sampled instruments. 

MIDI: Musical Instrument Digital Interface Specification 1.0, International MIDI Association, 
1983. 














IFF Specification: SMUS 401 


SSSP: See various articles on Structured Sound Synthesis Project in Foundations of Computer 
Music. 


Electronic Arts™ is a trademark of Electronic Arts. 
Amiga® is a registered trademark of Commodore-Amiga, Inc. 


2. Background 


Here’s some background information on score representation in general and design choices for 
SMUS. 


First, we’ll borrow some terminology from the Structured Sound Synthesis Project. [See the SSSP 
reference.] A "musical note” is one kind of scheduled event. Its properties include an event duration, 
an event delay, and a timbre object. The event duration tells the scheduler how long the note should 
last. The event delay tells how long after starting this note to wait before starting the next event. 
The timbre object selects sound driver data for the note; an "instrument" or "timbre". A "rest" is a 
sort of a null event. Its only property is an event delay. 


Classical Event Durations 


SMUS is geared for "classical" scores, not free-form performances. So its event durations are 
classical (whole note, dotted quarter rest, etc.). SMUS can tie notes together to build a "note event" 
with an unusual event duration. The set of useful classical durations is very small. So SMUS needs 
only a handful of bits to encode an event duration. This is very compact. It’s also very easy to 
display in Common Music Notation (CMN). 


Tracks 


The events in a SMUS score are grouped into parallel "tracks". Each track is a linear stream of 
events. 


Why use tracks? Tracks serve 4 functions: 


1. Tracks make it possible to encode event delays very compactly. A "classical" score has chorded 
notes and sequential notes; no overlapping notes. That is, each event begins either simultaneous 
with or immediately following the previous event in that track. So each event delay is either 0 
or the same as the event’s duration. This binary distinction requires only one bit of storage. 


2. Tracks represent the "voice tracks" in Common Music Notation. CMN organizes a score in 
parallel staves, with one or two "voice tracks" per staff. So one or two SMUS tracks represents 
a CMN staff. 


3. Tracks are a good match to available sound hardware. We can use "instrument settings" in a 
track to store the timbre assignments for that track’s notes. The instrument setting may change 
over the track. 


4. Furthermore, tracks can help to allocate notes among available output channels or performance 
devices or tape recorder "tracks". Tracks can also help to adapt polyphonic data to monophonic 
output channels. 


402 Amiga ROM Kernel Reference Manual: Devices 


5. Tracks are a good match to simple sound software. Each track is a place to hold state settings 
like "dynamic mark pp ", "time signature 3/4", "mute this track", etc., just as it’s a context for 
instrument settings. This is a lot like a text stream with running "font" and "face" properties 
(attributes). Running state is usually more compact than, say, storing an instrument setting in 
every note event. It’s also a useful way to organize "attributes" of notes. With "running track 


state" we can define new note attributes in an upward- and backward-compatible way. 


Running track state can be expanded (run decoded) while loading a track into memory or while 
playing the track. The runtime track state must be reinitialized every time the score is played. 


Separated vs. interleaved tracks. Multi-track data could be stored either as separate event streams 
or interleaved into one stream. To interleave the streams, each event has to carry a "track number" 
attribute. 


If we were designing an editable score format, we might interleave the streams so that nearby events 
are stored nearby. This helps when searching the data, especially if you can’t fit the entire score 
into memory at once. But it takes extra storage for the track numbers and may take extra work to 
manipulate the interleaved tracks. 


The musical score format FORM SMUS is intended for simple loading and playback of small scores 
that fit entirely in main memory. So we chose to store its tracks separately. 


There can be up to 255 tracks ina FORM SMUS. Each track is stored as a TRAK chunk. The count 
of tracks (the number of TRAK chunks) is recorded in the SHDR chunk at the beginning of the 
FORM SMUS. The TRAK chunks appear in numerical order 1, 2, 3, .... This is also priority order, 
most important track first. A player program that can handle up to N parallel tracks should read the 
first N tracks and ignore any others. 


The different tracks in a score may have different lengths. This is true both of storage length and of 
playback duration. 


Instrument Registers 


Instrument reference. In SSSP, each note event points to a "timbre object" which supplies the 
"instrument" (the sound driver data) for that note. FORM SMUS stores these pointers as a "current 
instrument setting" for each track. It’s just a run encoded version of the same information. SSSP 
uses a symbol table to hold all the pointers to "timbre object". SMUS uses INS1 chunks for the 
same purpose. They name the score’s instruments. 


The actual instrument data to use depends on the playback environment, but we want the score 
to be independent of environment. Different playback environments have different audio output 
hardware and different sound driver software. And there are channel allocation issues like how 
many output channels there are, which ones are polyphonic, and which I/O ports they’re connected 
to. If you use MIDI to control the instruments, you get into issues of what kind of device is 
listening to each MIDI channel and what each of its presets sounds like. If you use computer-based 
instruments, you need driver- specific data like waveform tables and oscillator parameters. 


We just want some orchestration. If the score wants a "piano", we let the playback program find a 
"piano". 


IFF Specification: SMUS 403 


Instrument reference by name. A reference from a SMUS score to actual instrument data is normally 
by name. The score simply names the instrument, for instance "tubular bells". It’s up to the player 
program to find suitable instrument data for its output devices. (More on locating instruments 
below.) 


Instrument reference by MIDI channel and preset. A SMUS score can also ask for a specific MIDI 
channel number and preset number. MIDI programs may honor these specific requests. But these 
channel allocations can become obsolete or the score may be played without MIDI hardware. In 
such cases, the player program should fall back to instrument reference by name. 


Instrument reference via instrument register. Each reference from a SMUS track to an instrument 
is via an "instrument register". Each track selects an instrument register which in tum points to the 
specific instrument data. 


Each score has an array of instrument registers. Each track has a "current instrument setting", which 
is simply an index number into this array. This is like setting a raster image’s pixel to a specific 
color number (a reference to a color value through a "color register") or setting a text character to a 
specific font number (a reference to a font through a "font register"). This is diagramed below: 


| Set inst 2 | Note | Note | Set inst 1 | Note | Note _ 


Ca oe 
"guitar" 


| Set inst 4 | Note | Note | Note | Note | Note | Note | | 














Locating instrument data by name. "INS1" chunks in a SMUS score name the instruments to use 
for that score. The player program uses these names to locate instrument data. 


To locate instrument data, the player performs these steps: 


For each right register, check for a suitable instrument with the right name... 
{Suitable" means usable with an available output device and driver. } 
{Use case independent name comparisons. } 


1. Initialize the instrument register to point to a built-in default instrument. 


2. Every player program must have default instruments. Simple programs stop here. For fancier 
programs, the default instruments are a backstop in case the search fails. 


. Check any instrument FORMs embedded in the FORM SMUS. (This is an "instrument cache".) 
. Else check the default instruments. 


. Else search the local "instrument library". (The library might simply be a disk directory.) 


nn & W 


. If all else fails, display the desired instrument name and ask the user to pick an available one. 


404 Amiga ROM Kernel Reference Manual: Devices 


This algorithm can be implemented to varying degrees of fanciness. It’s OK to stop searching after 
step 1, 2, 3, or 4. If exact instrument name matches fail, it’s OK to try approximate matches. E.g., 
search for any kind of "guitar" if you can’t find a "Spanish guitar". In any case, a player only has 
to search for instruments while loading a score. 


When the embedded instruments are suitable, they save the program from asking the user to insert 
the "right" disk in a drive and searching that disk for the "right" instrument. But it’s just a cache. In 
practice, we rarely move scores between environments so the cache often works. When the score 
is moved, embedded instruments must be discarded (a cache miss) and other instrument data used. 


Be careful to distinguish an instrument’s name from its filename—the contents name vs. container 
name. A musical instrument FORM should contain a NAME chunk that says what instrument it 
really is. Its filename, on the other hand, is a handle used to locate the FORM. Filenames are affected 
by external factors like drives, directories, and filename character and length limits. Instrument 
names are not. 


Issue: Consider instrument naming conventions for consistency. Consider a naming convention 
that aids approximate matches. E.g., we could accept "guitar, bass1" if we didn’t find "guitar, bass". 
Failing that, we could accept "guitar" or any name starting with "guitar". 


Set instrument events. If the player implements the set-instrument score event, each track can 
change instrument numbers while playing. That is, it can switch between the loaded instruments. 


Initial instrument settings. Each time a score is played, every track’s running state information must 
be initialized. Specifically, each track’s instrument number should be initialized to its track number. 
Track 1 to instrument 1, etc. It’s as if each track began with a set-instrument event. 


In this way, programs that don’t implement the set-instrument event still assign an instrument to 
each track. The INS1 chunks imply these initial instrument settings. 


MIDI Instruments 


As mentioned above, A SMUS score can also ask for MIDI instruments. This is done by putting 
the MIDI channel and preset numbers in an INS1 chunk with the instrument name. Some programs 
will honor these requests while others will just find instruments by name. 


MIDI Recorder and sequencer programs may simply transcribe the MIDI channel and preset com- 
mands in a recording session. For this purpose, set-MIDI-channel and set-MIDI-preset events can 
be embedded in a SMUS score’s tracks. Most programs should ignore these events. An editor 
program that wants to exchange scores with such programs should recognize these events. It should 
let the user change them to the more general set-instrument events. 


IFF Specification: SMUS 405 


3. Standard Data and Property Chunks 


A FORM SMUS contains a required property "SHDR" followed by any number of parallel "track" 
data chunks "TRAK". Optional property chunks such as "NAME", copyright "(c) ", and instrument 
reference "INS1" may also appear. Any of the properties may be shared over a LIST of FORMs 
SMUS by putting them in a PROP SMUS. [See the IFF reference.] 


Required Property SHDR 


The required property "SHDR" holds an SScoreHeader as defined in these C declarations and 
following documentation. An SHDR specifies global information for the score. It must appear 
before the TRAKs in a FORM SMUS. 

#define ID_SMUS MakeID(’S’, ‘'M’, 'U’, ‘S‘) 

#define ID _SHDR MakeID(’S’, ’H’, 'D’, ‘'R‘) 


typedef struct { 
UWORD tempo; /* tempo, 128ths quarter note/minute */ 
UBYTE volume; /* overall playback volume 0 through 127 */ 
UBYTE ctTrack; /* count of tracks in the score */ 
} SScoreHeader; 


{Implementation details. In the C struct definitions in this memo, fields are filed in the order shown. 
A UBYTE field is packed into an 8-bit byte. Programs should set all "pad" fields to 0. MakelID is a 
C macro defined in the main IFF document and in the source file IFF.h.]} 


The field tempo gives the nominal tempo for all tracks in the score. It is expressed in 128ths of a 
quarter note per minute, i.e., 1 represents 1 quarter note per 128 minutes while 12800 represents 
100 quarter notes per minute. You may think of this as a fixed point fraction with a 9-bit integer 
part and a 7-bit fractional part (to the right of the point). A coarse-tempoed program may simply 
shift tempo right by 7 bits to get a whole number of quarter notes per minute. The tempo field can 
store tempi in the range 0 up to 512. The playback program may adjust this tempo, perhaps under 
user control. 


Actually, this global tempo could actually be just an initial tempo if there are any "set tempo" 
SEvents inside the score (see TRAK, below). Or the global tempo could be scaled by "scale tempo" 
SEvents inside the score. These are potential extensions that can safely be ignored by current 
programs. [See More SEvents To Be Defined, below.] 


The field volume gives an overall nominal playback volume for all tracks in the score. The range 
of volume values O through 127 is like a MIDI key velocity value. The playback program may 
adjust this volume, perhaps under direction of a user "volume control”. 


Actually, this global volume level could be scaled by dynamic-mark SEvents inside the score (see 
TRAK, below). 


The field ct Track holds the count of tracks, i.e., the number of TRAK chunks in the FORM SMUS 
(see below). This information helps the reader prepare for the following data. 


A playback program will typically load the score and call a driver routine PlayScore(tracks, 
tempo, volume), supplying the tempo and volume from the SHDR chunk. 


406 Amiga ROM Kernel Reference Manual: Devices 


Optional Text Chunks NAME, (c), AUTH, ANNO 
Several text chunks may be included ina FORM SMUS to keep ancillary information. 
The optional property "NAME" names the musical score, for instance "Fugue in C". 


The optional property "(c) " holds a copyright notice for the score. The chunk ID "(c) " serves the 
function of the copyright characters "© ". E.g., a "(c) " chunk containing "1986 Electronic Arts" 
means "© 1986 Electronic Arts". 


The optional property "AUTH" holds the name of the score’s author. 


The chunk types "NAME", "(c)", and "AUTH" are property chunks. Putting more than one NAME 
(or other) property in a FORM is redundant. Just the last NAME counts. A property should be 
shorter than 256 characters. Properties can appear in a PROP SMUS to share them over a LIST of 
FORMs SMUS. 


The optional data chunk "ANNO" holds any text annotations typed in by the author. 


An ANNO chunk is not a property chunk, so you can put more than one ina FORM SMUS. You 
can make ANNO chunks any length up to 23! — 1 characters, but 32767 is a practical limit. Since 
they’re not properties, ANNO chunks don’t belong in a PROP SMUS. That means they can’t be 
shared over a LIST of FORMs SMUS. 


Syntactically, each of these chunks contains an array of 8-bit ASCII characters in the range 
(SP, hex 20) through "~" (tilde, hex 7F), just like a standard "TEXT" chunk. [See "Strings, String 


wot 


chunk’s ckSize field holds the count of characters. 





#define ID NAME MakeID(’N’, ‘A’, 'M’, 'E‘) 
/* NAME chunk contains a CHAR[], the musical score’s name. x/ 


#define ID Copyright MakeID(’(’, ‘'c’, ')', ’ ') 
/* "(c) " chunk contains a CHAR[], the FORM’s copyright notice. */ 


#define ID_AUTH MakeID(‘A’, ‘U’, ‘T’, ‘H’) 
/* AUTH chunk contains a CHAR[], the name of the score’s author. */ 


#define ID_ANNO MakeID(’A’, ‘N’, 'N’, '0’) 
/* ANNO chunk contains a CHAR[], author’s text annotations. */ 


Remember to store a 0 pad byte after any odd-length chunk. 


Optional Property INS1 


The "INS1" chunks ina FORM SMUS identify the instruments to use for this score. A program can 
ignore INS1 chunks and stick with its built-in default instrument assignments. Or it can use them 
to locate instrument data. [See "Instrument Registers" in section 2, above.] 


#define ID_INS1 MakeID(‘’I’, ‘’N’, ’S’, '1°) 


/* Values for the RefInstrument field "type". */ 
#define INS1 Name 0 /* just use the name; ignore datal, data2 */ 
#define INS1_ MIDI 1 /* <datal, data2> = MIDI <channel, preset> */ 


typedef struct { 


UBYTE register; /* set this instrument register number */ 
UBYTE type; /* instrument reference type */ 

UBYTE datal, data2; /* depends on the "type" field */ 

CHAR name[]; /* instrument name */ 


} RefInstrument; 


IFF Specification: SMUS 407 


An INS1 chunk names the instrument for instrument register number register. The register 
field can range from O through 255. In practice, most scores will need only a few instrument 
registers. 


The name field gives a text name for the instrument. The string length can be determined from the 
ckSize of the INS1 chunk. The string is simply an array of 8-bit ASCII characters in the range " " 
(SP, hex 20) through "™" (tilde, hex 7F). 


Besides the instrument name, an INS1 chunk has two data numbers to help locate an instrument. 
The use of these data numbers is controlled by the type field. Avaluetype = INS1_Name means 
just find an instrument by name. In this case, data1 and data2 should just be set to 0. A value 
type = INS1_MIDI means look for an instrument on MIDI channel # datal, preset # data2. 
Programs and computers without MIDI outputs will just ignore the MIDI data. They’ll always look 
for the named instrument. Other values of the type field are reserved for future standardization. 


See section 2, above, for the algorithm for locating instrument data by name. 


Obsolete Property INST 
The chunk type "INST" is obsolete in SMUS. It was revised to form the "INS1" chunk. 


Data Chunk TRAK 


The main contents of a score is stored in one or more TRAK chunks representing parallel "tracks". 
One TRAK chunk per track. 


The contents of a TRAK chunk is an array of 16-bit "events" such as "note", "rest", and "set 
instrument". Events are really commands to a simple scheduler, stored in time order. The tracks 
can be polyphonic, that is, they can contain chorded "note" events. 


Each event is stored as an "SEvent" record. ("SEvent" means "simple musical event".) Each SEvent 
has an 8-bit type field called an "sID" and 8 bits of type-dependent data. This is like a machine 
language instruction with an 8-bit opcode and an 8-bit operand. 


This format is extensible since new event types can be defined in the future. The "note" and "rest" 
events are the only ones that every program must understand. We will carefully design any new 
event types so that programs can Safely skip over unrecognized events in a score. 


Caution: ID codes must be allocated by a central clearinghouse to avoid conflicts. Commodore 
Applications and Technical Support provides this clearinghouse service. 


Here are the C type definitions for TRAK and SEvent and the currently defined sID values. Afterward 
are details on each SEvent. 


#define ID_TRAK MakeID('T’, ‘R’, ‘A’, 'K‘) 


/* TRAK chunk contains an SEvent[]. */ 
/* SEvent: Simple musical event. */ 
typedef struct { 
UBYTE sID; /* SEvent type code */ 
UBYTE data; /* sID-dependent data */ 
} SEvent; 
/* SEvent type codes "sID". */ 
#define SID FirstNote 0 


#define SID LastNote 127 /* sIDs in the range SID FirstNote through 
* SID_LastNote (sign bit = 0) are notes. 
* The sID is the MIDI tone number (pitch) .*/ 


#define SID Rest 128 /* a rest (same data format as a note). */ 


408 Amiga ROM Kernel Reference Manual: Devices 


#define SID Instrument 129 /* set instrument number for this track. */ 
#define SID TimeSig 130 /* set time signature for this track. */ 
#define SID KeySig 131 /* set key signature for this track. */ 
#define SID Dynamic 132 /* set volume for this track. */ 
#define SID _MIDI_Chnl 133 /* set MIDI channel number (sequencers) */ 
#define SID MIDI Preset 134 /* set MIDI preset number (sequencers) */ 
#define SID Clef 135 /* inline clef change. 

* 0=Treble, 1=Bass, 2=Alto, 3=Tenor. (new) */ 
#define SID Tempo 136 /* Inline tempo in beats per minute.(new) */ 
/* SID values 144 through 159: reserved for Instant Music SEvents. */ 
/* Remaining sID values up through 254: reserved for future 
* standardization. */ 
#define SID_ Mark 255 /* sID reserved for an end-mark in RAM. */ 


Note and Rest SEvents 


The note and rest SEvents SID_FirstNote through SID_Rest have the following structure 
overlaid onto the SEvent structure: 


typedef struct { 
UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */ 
* 


unsigned chord 1, /* 1 = a chorded note 
tieOut #1, /* 1 = tied to the next note or chord */ 
nTuplet 2, /* 0 = none, 1 = triplet, 2 = quintuplet, 

* 3 = septuplet x 
dot ly /* dotted note; multiply duration by 3/2 */ 
division :3; /* basic note duration is 2°-division: 0 = 

* whole note, 1 = half note, 2 = quarter 

* note, .... 7 = 128th note * 


} SNote; 


[Implementation details. Unsigned ":n" fields are packed into n bits in the order shown, most 
significant bit to least significant bit. An SNote fits into 16 bits like any other SEvent. Waming: 
Some compilers don’t implement bit-packed fields properly. E.g., Lattice 68000 C pads a group of 
bit fields out to a LONG, which would make SNote take 5-bytes! In that situation, use the bit-field 
constants defined below.] 


The SNote structure describes one "note" or "rest" in a track. The field SNote.tone, which is 
overlaid with the SEvent . sID field, indicates the MIDI tone number (pitch) in the range 0 through 
127. A value of 128 indicates a rest. 


The fields nTuplet, dot, and division together give the duration of the note or rest. The division 
gives the basic duration: whole note, half note, etc. The dot indicates if the note or rest is dotted. A 
dotted note is 3/2 as long as an undotted note. The value nTuplet (0 through 3) tells if this note or 
rest is part of an N-tuplet of order 1 (normal), 3, 5, or 7; an N-tuplet of order (2 * nTuplet + 1). 
A triplet note is 2/3 as long as a normal note, while a quintuplet is 4/5 as long and a septuplet is 6/7 
as long. 


Putting these three fields together, the duration of the note or rest is 
Q-division » (1, 3/2} * {1, 2/3, 4/5, 6/7} 


These three fields are contiguous so you can easily convert to your local duration encoding by using 
the combined 6 bits as an index into a mapping table. 


The field chord indicates if the note is chorded with the following note (which is supposed to have 
the same duration). A group of notes may be chorded together by setting the chord bit of all but 
the last one. (In the terminology of SSSP and GSCR, setting the chord bit to 1 makes the "entry 


IFF Specification: SMUS 409 


delay" 0.) A monophonic-track player can simply ignore any SNote event whose chord bit is set, 
either by discarding it when reading the track or by skipping it when playing the track. 


Programs that create polyphonic tracks are expected to store the most important note of each chord 
last, which is the note with the 0 chord bit. This way, monophonic programs will play the most 
important note of the chord. The most important note might be the chord’s root note or its melody 
note. 


If the field tieOut is set, the note is tied to the following note in the track if the following note 
has the same pitch. A group of tied notes is played as a single note whose duration is the sum of 
the component durations. Actually, the tie mechanism ties a group of one or more chorded notes to 
another group of one or more chorded notes. Every note in a tied chord should have its tieOut bit 
set. 


Of course, the chord and tieOut fields don’t apply to SID_Rest SEvents. 


Programs should be robust enough to ignore an unresolved tie, i.e., a note whose tieOut bit is set 
but isn’t followed by a note of the same pitch. If that’s true, monophonic-track programs can simply 
ignore chorded notes even in the presense of ties. That is, tied chords pose no extra problems. 


The following diagram shows some combinations of notes and chords tied to notes and chords. The 
text below the staff has a column for each SNote SEvent to show the pitch, chord bit, and tieOut 
bit. 


A treble staff with chords and ties: 





Corresponding SNote values in the TRAK chunk: 


Pitch: DBG DBG DBG G DBG B B DBG 
chord: cc - cc- ec- - ecc- - - cece 
tieOut: ttt Sie. tet = Cott = © =) Ss 


If you read the above track into a monophonic-track program, it’ll strip out the chorded notes and 
ignore unresolved ties. You'll end up with: 





Pitch G G G G G B B G 
chord 7 - 7 = = = = - 
tieOut: t - t a (t) = (t) 


A rest event (SID = SID_Rest) has the same SEvent . data field as a note. It tells the duration 
of the rest. The chord and tieOut fields of rest events are ignored. 


Within a TRAK chunk, note and rest events appear in time order. 


410 Amiga ROM Kernel Reference Manual: Devices 


Instead of the bit-packed structure SNote, it might be easier to assemble data values by or- 
ing constants and to disassemble them by masking and shifting. In that case, use the following 


definitions. 
#define noteChord (1<<7) /* note is chorded to next note */ 
#define noteTieOut (1<<6) /* tied to next note/chord */ 
#define noteNShift 4 /* shift count for nTuplet field */ 
#define noteN3 (1<<noteNShift) /* note is a triplet */ 
#define noteN5 (2<<noteNShift) /* note is a quintuplet */ 
#define noteN7 (3<<noteNShift) /* note is a septuplet */ 
#define noteNMask noteN7 * bit mask for the nTuplet field */ 
#define noteDot (1<<3) /* note is dotted */ 
#define noteD1l 0 /* whole note division */ 
#define noteD2 1 /* half note division */ 
#define noteD4 2 /* quarter note division */ 
#define noteD8 3 /* eighth note division */ 
#define noteD16 4 /* sixteenth note division */ 
#define noteD32 5 /* thirty-secondth note division */ 
#define noteDé4 6 /* sixty-fourth note division ey 
#define noteD128 7 /* 1/128 note division */ 
#define noteDMask noteD128 /* bit mask for the division field */ 


#define noteDurMask 0x3F mask for combined duration fields*/ 


Note: The remaining SEvent types are optional. A writer program doesn’t have to generate them. 
A reader program can safely ignore them. 


Set Instrument SEvent 


One of the running state variables of every track is an instrument number. An instrument number is 
the array index of an "instrument register", which in tum points to an instrument. (See "Instrument 
Registers", in section 2.) This is like a color number in a bitmap; a reference to a color through a 
"color register”. 


The initial setting for each track’s instrument number is the track number. Track 1 is set to instrument 
1, etc. Each time the score is played, every track’s instrument number should be reset to the track 
number. 


The SEvent SID_Inst rument changes the instrument number for a track, that is, which instrument 
plays the following notes. Its SEvent .data field is an instrument register number in the range 0 
through 255. If a program doesn’t implement the SID_Inst rument event, each track is fixed to 
one instrument. 


Set Time Signature SEvent 


The SEvent SID_TimeSig sets the time signature for the track. A "time signature" SEvent has the 
following structure overlaid on the SEvent structure: 


typedef struct { 
UBYTE type; 
unsigned timeNSig :5, 
timeDSig :3; 


/* = SID TimeSig */ 

/* time sig. "numerator" is timeNSig + 1 */ 

/* time sig. "denominator" is 2*timeDSig:* 
* 0 = whole note, 1 = half note, 2 = * 
* quarter note,....7 = 128th note */ 

} STimeSig; 


{Implementation details. Unsigned ":n" fields are packed into n bits in the order shown, most 
significant bit to least significant bit. An STimeSig fits into 16 bits like any other SEvent. Waming: 
Some compilers don’t implement bit-packed fields properly. E.g., Lattice C pads a group of bit 


IFF Specification: SMUS 411 


fields out to a LONG, which would make an STimeSig take 5-bytes! In that situation, use the 
bit-field constants defined below.] 


The field type contains the value SID_TimeSig, indicating that this SEvent is a "time signature" 
event. The field timeNSig indicates the time signature "numerator" is timeNSig + 1, that is, 
1 through 32 beats per measure. The field timeDSig indicates the time signature "denominator" 
is 2%meDSig that is each "beat" is a 2*™°PSig note (see SNote division, above). So 4/4 time is 
expressed as timeNSig = 3,timeDSig = 2. 


The default time signature is 4/4 time. Be aware that the time signature has no effect on the 
score’s playback. Tempo is uniformly expressed in quarter notes per minute, independent of time 
signature. (Quarter notes per minute would equal beats per minute only if timeDSig = 2, n/4 
time). Nonetheless, any program that has time signatures should put them at the beginning of each 
TRAK when creating a FORM SMUS because music editors need them. 


Instead of the bit-packed structure STimeSig, it might be easier to assemble data values by or- 
ing constants and to disassemble them by masking and shifting. In that case, use the following 
definitions. 


#define timeNMask OxF8 /* bit mask for the timeNSig field XY, 
#define timeNShift 3 /* shift count for timeNSig field x/ 
#define timeDMask 0x07 /* bit mask for the timeDSig field */ 


Key Signature SEvent 


An SEvent SID_KeySig sets the key signature for the track. Its data field is a UBYTE number 
encoding a major key: 


data key music notation data key music notation 
0 Cc maj 

1 G # 8 F b 

2 D ## 9 Bb bb 

3 A ### 10 Eb bbb 

4 E HHH 11 Ab bbbb 

5 B HEH HE 12 Db bbbbb 

6 F# HHH tt 13 Gb bbbbbb 

7 C# HHHt HHH 14 Cb bbbbbbb 


A SID_KeySig SEvent changes the key for the following notes in that track. C major is the default 
key in every track before the first SID_KeySig SEvent. 


Dynamic Mark SEvent 


An SEvent SID_Dynamic represents a dynamic mark like ppp and fff in Common Music Notation. 
Its data field is a MIDI key velocity number 0 through 127. This sets a "volume control" for 
following notes in the track. This "track volume control" is scaled by the overall score volume in 
the SHDR chunk. The default dynamic level is 127 (full volume). 


Set MIDI Channel SEvent 


The SEvent SID_MIDI_Chn1 is for recorder programs to record the set-MIDI-channel low level 
event. The data byte contains a MIDI channel number. Other programs should use instrument 
registers instead. 


412 Amiga ROM Kernel Reference Manual: Devices 


Set MIDI Preset SEvent 


The SEvent SID_MIDI_Preset is for recorder programs to record the set-MIDI-preset low level 
event. The data byte contains a MIDI preset number. Other programs should use instrument 
registers instead. 








Instant Music Private SEvents 
Sixteen SEvents are used for private data for the Instant Music program. SID values 144 through 
159 are reserved for this purpose. Other programs should skip over these SEvents. 
End-Mark SEvent 


The SEvent type SID_Mark is reserved for an end marker in working memory. This event is never 
Stored in a file. It may be useful if you decide to use the filed TRAK format intact in working 
memory. 





More SEvents can be defined in the future. The sID codes 133 through 143 and 160 through 254 
are reserved for future needs. Caution: sID codes must be allocated by a central "clearinghouse" to 
avoid conflicts. 


The following SEvent types are under consideration and should not yet be used. 


Issue: A "change tempo" SEvent changes tempo during a score. Changing the tempo affects all 
tracks, not just the track containing the change tempo event. 


One possibility is a "scale tempo" SEvent SID_ScaleTempo that rescales the global tempo: 


currentTempo := globalTempo * (data + 1) / 128 


This can scale the global tempo (in the SHDR) anywhere from x1/128 to x2 in roughly 1% 
increments. 


An alternative is two events SID_SetHTempo and SID_Set LTempo. SID_SetHTempo gives the 
high byte and SID_SetLTempo gives the low byte of a new tempo setting, in 128ths quarter 
note/minute. SetHTempo automatically sets the low byte to 0, so the SetLTempo event isn’t 
needed for coarse settings. In this scheme, the SHDR’s tempo is simply a starting tempo. 


An advantage of SID_ScaleTempo is that the playback program can just alter the global tempo to 
adjust the overall performance time and still easily implement tempo variations during the score. 
But the "set tempo" SEvent may be simpler to generate. 


Issue: The events SID_BeginRepeat and SID_EndRepeat define a repeat span for one track. The 
span of events between a BeginRepeat and an EndRepeat is played twice. The SEvent .data 
field in the BeginRepeat event could give an iteration count, 1 through 255 times or 0 for "repeat 
forever". 


Repeat spans can be nested. All repeat spans automatically end at the end of the track. 


An event SID_Ending begins a section like "first ending" or "second ending”. The SEvent.data 
field gives the ending number. This SID_Ending event only applies to the innermost repeat group. 
(Consider generalizing it.) 


IFF Specification: SMUS 413 


A more general alternative is a "subtrack" or "subscore" event. A "subtrack" event is essentially 
a "subroutine call" to another series of SEvents. This is a nice way to encode all the possible 
variations of repeats, first endings, codas, and such. 


To define a subtrack, we must demark its start and end. One possibility is to define a relative branch- 
to-subtrack event SID_BSR and a retum-from-subtrack event SID_RTS. The 8-bit data field in the 
SID_BSR event can reach as far as 512 SEvents. A second possibility is to call a subtrack by index 
number, with an IFF chunk outside the TRAK defining the start and end of all subtracks. This is 
very general since a portion of one subtrack can be used as another subtrack. It also models the 
tape recording practice of first "laying down a track" and then selecting portions of it to play and 
repeat. To embody the music theory idea of playing a sequence like "ABBA", just compose the 
"main" track entirely of subtrack events. A third possibility is to use a numbered subtrack chunk 
"STRK" for each subroutine. 


4. Private Chunks 


As in any IFF FORM, there can be private chunks in a FORM SMUS that are designed for one 
particular program to store its private information. All IFF reader programs skip over unrecognized 
chunks, so the presense of private chunks can’t hurt. 


Instant Music stores some global score information in a chunk of ID "IRev" and some other 
information in a chunk of ID "BIAS". 


414 Amiga ROM Kernel Reference Manual: Devices 


Appendix A. Quick Reference 


Type Definitions 


Here’s a collection of the C type definitions in this memo. In the "struct" type definitions, fields 
are filed in the order shown. A UBYTE field is packed into an 8-bit byte. Programs should set all 
"pad" fields to 0. 


#define ID_SMUS MakeID(’S’, ‘M’, ‘U’, 'S’) 
#define ID_SHDR MakeID(’S’, 'H’, ‘D’, 'R’) 


typedef struct { 


UWORD tempo; /* tempo, 128ths quarter note/minute */ 
UBYTE volume; /* overall playback volume 0 through 127 */ 
UBYTE ctTrack; /* count of tracks in the score */ 


} SScoreHeader; 


#define ID_NAME MakeID(’N’, ‘A’, 'M’, 'E’) 


/* NAME chunk contains a CHAR[], the musical score’s name. */ 
#define ID Copyright MakeID(’(’, ‘'c’, ')’, ' ") 
/* "(c) ™" chunk contains a CHAR[], the FORM’s copyright notice. */ 
#define ID_AUTH MakeID(’A’, 'U"’, 'T’, ‘H’) 
/* AUTH chunk contains a CHAR[], the name of the score’s author. x/ 
#define ID_ANNO MakeID(’A’, 'N’, 'N’, '0°) 
/* ANNO chunk contains a CHAR[], author’s text annotations. */ 
#define ID_INS1 MakeID(‘’I’, ‘N’, ‘S’, '1°) 
/* Values for the RefInstrument field "type". */ 
#define INS1_ Name 0 /* just use the name; ignore datal, data2 */ 
#define INS1_ MIDI 1 /* <datal, data2> = MIDI <channel, preset> */ 
typedef struct { 
UBYTE register; /* set this instrument register number */ 
UBYTE type; /* instrument reference type */ 
UBYTE datal, data2; /* depends on the "type" field */ 
CHAR name[]; /* instrument name */ 


} RefInstrument; 


#define ID_TRAK MakeID(’T’, 'R’, ‘A’, 'K‘) 


/* TRAK chunk contains an SEvent([]. */ 
/* SEvent: Simple musical event. */ 
typedef struct { 
UBYTE sID; /* SEvent type code */ 
UBYTE data; /* sID-dependent data */ 
} SEvent; 
/* SEvent type codes "sID". */ 
#define SID _FirstNote 0 


#define SID_LastNote 127 /* sIDs in the range SID FirstNote through 
* SID LastNote (sign bit = 0) are notes. The 
* sID is the MIDI tone number (pitch). */ 


#define SID Rest 128 /* a rest (same data format as a note). */ 
#define SID Instrument 129 /* set instrument number for this track.*/ 
#define SID TimeSig 130 /* set time signature for this track. */ 
#define SID _KeySig 131 /* set key signature for this track. x/ 
#define SID Dynamic 132 /* set volume for this track. */ 


#define SID_MIDI_Chnl 133 /* set MIDI channel number (sequencers) */ 
#define SID MIDI Preset 134 /* set MIDI preset number (sequencers) */ 
* 


#define SID Clef 135 /* inline clef change. 
* 0=Treble, 1=Bass, 2=Alto, 3=Tenor. x/ 
#define SID_ Tempo 136 /* Inline tempo in beats per minute. x/ 


/* SID values 144 through 159: reserved for Instant Music SEvents. */ 


/* Remaining sID values up through 254: reserved for future 
* standardization. */ 


IFF Specification: SMUS 415 


#define SID Mark 255 /* sID reserved for an end-mark in RAM. */ 
/* SID _FirstNote..SID_LastNote, SID Rest SEvents */ 
typedef struct { 
UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */ 
unsigned chord :1, /* 1 = a chorded note */ 
tieOut :1, /* 1 = tied to the next note or chord */ 
nTuplet :2, /* 0 = none, 1 = triplet, 2 = quintuplet, 

* 3 = septuplet */ 
dot el, /* dotted note; multiply duration by 3/2 */ 
division :3; /* basic note duration is 2-division: 0 = whole 

* note, 1 = half note, 2 = quarter note, 

* 7 = 128th note */ 
} SNote; 

#define noteChord (1<<7) /* note is chorded to next note */ 
#define noteTieOut (1<<6) /* tied to next note/chord */ 
#define noteNShift 4 /* shift count for nTuplet field */ 
#define noteN3 (1<<noteNShift) /* note is a triplet */ 
#define noteNS (2<<noteNShift) /* note is a quintuplet x/ 
#define noteN7 (3<<noteNShift) /* note is a septuplet */ 
#define noteNMask noteN7 /* bit mask for the nTuplet field */ 
#define noteDot (1<<3) /* note is dotted */ 
#define noteD1l 0 /* whole note division «/ 
#define noteD2 1 /* half note division */ 
#define noteD4 2 /* quarter note division */ 
#define noteD8& 3 /* eighth note division */ 
#define noteD16 4 /* sixteenth note division */ 
#define noteD32 5 /* thirty-secondth note division */ 
#define noteD64 6 /* sixty-fourth note division */ 
#define noteD128 7 /* 1/128 note division */ 
#define noteDMask noteD128 /* bit mask for the division field */ 
#define noteDurMask 0x3F /* mask for combined duration fields */ 
/* SID_Instrument SEvent */ 
/* "data" value is an instrument register number 0 through 255. */ 
/* SID TimeSig SEvent */ 
typedef struct { 

UBYTE type; /* = SID TimeSig */ 


unsigned timeNSig :5, /* time sig. "numerator" is timeNSig + 1 */ 
timeDSig :3; /* time sig. "denominator" is 2*timeDSig: * 


* 0 = whole note, 1 = half note, 2 = * 
* quarter note,.... 7 = 128th note */ 
} STimeSig; 

#define timeNMask O0xF8 /* bit mask for the timeNSig field */ 
#define timeNShift 3 /* shift count for timeNSig field */ 
#define timeDMask 0x07 /* bit mask for the timeDSig field */ 
/* SID KeySig SEvent */ 
/* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#; * 
* 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb. */ 
/* SID Dynamic SEvent */ 
/* "data" value is a MIDI key velocity 0..127. */ 


416 Amiga ROM Kernel Reference Manual: Devices 


SMUS Regular Expression 


Here’s a regular expression summary of the FORM SMUS syntax. This could be an IFF file or part 


of one. 


SMUS 


SHDR 
NAME 
IRev 


ANNO 
INS1 


TRAK 


InstrForm ;: 


Copyright be 
AUTH : 


"FORM" 


"SHDR" 
"NAME" 
" (c) w" 
"AUTH" 
"IRev" 


"ANNO" 
"INS1" 


"?PRAK" 
"FORM" 


#{ 


#{ 
#{ 
#{ 
#{ 
#{ 
#{ 
#{ 
#{ 
#{ 


"SMUS" SHDR [NAME] [Copyright] [AUTH] [IRev] 
ANNO* INS1* TRAK* InstrForm* } 


SScoreHeader } 
CHAR* } (0) 
CHAR* } [0] 
CHAR* } [0] 

nashe: } 


CHAR* } [0] 
RefInstrument } [0) 


SEvent* } 
Seve } 


The token "#" represents a ckSize LONG count of the following {braced} data bytes. Literal items 
are shown in "quotes", [square bracket items] are optional, and "*" means 0 or more replications. 
A sometimes-needed pad byte is shown as "[0]". 


Actually, the order of chunks in a FORM SMUS is not as strict as this regular expression indicates. 
The SHDR, NAME, Copyright, AUTH, IRev, ANNO, and INS1 chunks may appear in any order, 
as long as they precede the TRAK chunks. 


The chunk "Inst rForm" represents any kind of instrument data FORM embedded in the FORM 
SMUS. For example, see the document "8SVX" IFF 8-Bit Sampled Voice. Of course, a recipient 
program will ignore an instrument FORM if it doesn’t recognize that FORM type. 


IFF Specification: SMUS 417 


Appendix B. SMUS Example 


Here’s a box diagram for a simple example, a SMUS with two instruments and two tracks. Each 
track contains 1 note event and 1 rest event. 


‘NAME’ 


94 1, 0, 0, 0, ‘piano’ 


0 
‘INS1° 10 


2, 0, 0, 0, ‘guitar’ 
‘TRAK!’ 4 


60, 16, 128, 16 


‘TRAK’ 4 


128, 16, 60, 16 





The "0" after the first INS1 chunk is a pad byte. 


Appendix C. Standards Committee 
The following people contributed to the design of this SMUS standard: 


Ralph Bellafatto, Cherry Lane Technologies 
Geoff Brown, Uhuru Sound Software 

Steve Hayes, Electronic Arts 

Jerry Morrison, Electronic Arts 


418 Amiga ROM Kernel Reference Manual: Devices 


"8SVX" IFF 8-Bit Sampled Voice 


Date: February 7, 1985 (Re-Typeset Oct, 1988 Commodore-Amiga, Inc.) 
From: = Steve Hayes and Jerry Morrison, Electronic Arts 
Status: Adopted 


1. Introduction 


This is the IFF supplement for FORM "8SVX". An 8SVX is an IFF "data section" or "FORM" 
(which can be an IFF file or a part of one) containing a digitally sampled audio voice consisting of 
8-bit samples. A voice can be a one-shot sound or—with repetition and pitch scaling—a musical 
instrument. "EA IFF 85" is Electronic Arts’ standard interchange file format. [See "EA IFF 85" 
Standard for Interchange Format Files.] 








The 8SVX format is designed for playback hardware that uses 8-bit samples attenuated by a volume 
control for good overall signal-to-noise ratio. Soa FORM 8SVX stores 8-bit samples and a volume 
level. 


A similar data format (or two) will be needed for higher resolution samples (typically 12 or 16 
bits). Properly converting a high resolution sample down to 8 bits requires one pass over the data 
to find the minimum and maximum values and a second pass to scale each sample into the range 
-128 through 127. So it’s reasonable to store higher resolution data in a different FORM type and 
convert between them. 


For instruments, FORM 8SVX can record a repeating waveform optionally preceded by a startup 
transient waveform. These two recorded signals can be pre-synthesized or sampled from an acoustic 
instrument. For many instruments, this representation is compact. FORM 8SVX< is less practical 
for an instrument whose waveform changes from cycle to cycle like a plucked string, where a long 
sample is needed for accurate results. 


FORM 8SVX can store an "envelope" or "amplitude contour" to enrich musical notes. A future 
voice FORM could also store amplitude, frequency, and filter modulations. 


FORM 8SVX< is geared for relatively simple musical voices, where one waveform per octave is 
sufficient, the waveforms for the different octaves follow a factor-of-two size rule, and one envelope 
is adequate for all octaves. You could store a more general voice as a LIST containing one or more 
FORMs 8SVX per octave. A future voice FORM could go beyond one "one-shot" waveform and 
one "repeat" waveform per octave. 


Section 2 defines the required property sound header "VHDR", optional properties name "NAME", 
copyright "(c) ", and author "AUTH", the optional annotation data chunk "ANNO", the required 
data chunk "BODY", and optional envelope chunks "ATAK" and "RLSE". These are the "standard" 
chunks. Specialized chunks for private or future needs can be added later, e.g., to hold a frequency 
contour or Fourier series coefficients. The 8SVX syntax is summarized in Appendix A as a regular 
expression and in Appendix B as an example box diagram. Appendix C explains the optional 
Fibonacci-delta compression algorithm. 


Reference: 


"EA IFF 85" Standard for Interchange Format Files describes the conventions for all IFF files. 
Amiga is a registered trademark of Commodore-Amiga, Inc. 
Electronic Arts™ is a trademark of Electronic Arts. 


IFF Specification: 8SVX 419 


2. Standard Data and Property Chunks 


FORM 8SVX< stores all the waveform data in one body chunk "BODY". It stores playback 
parameters in the required header chunk "VHDR". "VHDR" and any optional property chunks 
"NAME", "(c) ", and "AUTH" must all appear before the BODY chunk. Any of these properties 
may be shared over a LIST of FORMs 8SVX by putting them in a PROP 8SVX. [See "EA IFF 85" 
Standard for Interchange Format Files.] 


Background 


There are two ways to use FORM 8SVX: as a one-shot sampled sound or as a sampled musical 
instrument that plays "notes". Storing both kinds of sounds in the same kind of FORM makes it 
easy to play a one-shot sound as an instrument or an instrument as a one-note sound. 


A one-shot sound is a series of audio data samples with a nominal playback rate and amplitude. 
The recipient program can optionally adjust or modulate the amplitude and playback data rate. 


For musical instruments, the idea is to store a sampled (or pre-synthesized) waveform that will be 
parameterized by pitch, duration, and amplitude to play each "note". The creator of the FORM 
8SVX can supply a waveform per octave over a range of octaves for this purpose. The intent is to 
perform a pitch by selecting the closest octave’s waveform and scaling the playback data rate. An 
optional "one-shot" waveform supplies an arbitrary startup transient, then a "repeat" waveform is 
iterated as long as necessary to sustain the note. 


A FORM 8SV<X can also store an envelope to modulate the waveform. Envelopes are mostly useful 
for variable-duration notes but could be used for one-shot sounds, too. 


The FORM 8SV<X standard has some restrictions. For example, each octave of data must be twice 
as long as the next higher octave. Most sound driver software and hardware imposes additional 
restrictions. E.g., the Amiga sound hardware requires an even number of samples in each one-shot 
and repeat waveform. 


Required Property VHDR 


The required property "VHDR" holds a Voice8 Header structure as defined in these C declarations and 
following documentation. This structure holds the playback parameters for the sampled waveforms 
in the BODY chunk. (See "Data Chunk BODY", below, for the storage layout of these waveforms.) 


#define ID_8SVX MakeID(’8’, 'S’, ’V', ¢X’) 
#define ID VHDR MakeID('V’, ‘H’, 'D’, 'R‘) 


typedef LONG Fixed; /* A fixed-point value, 16 bits to the left of the 
point and 16 to the right. A Fixed is a number 
of 2°16ths, i.e., 65536ths. x/ 
#define Unity 0x1l0000L /* Unity = Fixed 1.0 = maximum volume */ 
/* sCompression: Choice of compression algorithm applied to the samples. */ 
#define sCmpNone 0 /* not compressed */ 
#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */ 
/* Can be more kinds in the future. */ 


typedef struct { 
ULONG oneShotHiSamples, /* # samples in the high octave 1l-shot part */ 
repeatHiSamples, /* # samples in the high octave repeat part */ 
samplesPerHiCycle;/* # samples/cycle in high octave, else 0 */ 


UWORD samplesPerSec; /* data sampling rate */ 
UBYTE ctOctave, /* # octaves of waveforms x/ 
sCompression; /* data compression technique used */ 
Fixed volume; /* playback volume from 0 to Unity (full 
* volume). Map this value into the output 
* hardware’s dynamic range. x/ 
} Voice8Header; 


420 Amiga ROM Kernel Reference Manual: Devices 


[Implementation details. Fields are filed in the order shown. The UBYTE fields are byte-packed 
(2 per 16-bit word). MakeID is a C macro defined in the main IFF document and in the source file 
IFF.h.] 


A FORM 8SVX holds waveform data for one or more octaves, each containing a one-shot part and 
a repeat part. The fields oneShotHiSamples and repeatHiSamples tell the number of audio 
samples in the two parts of the highest frequency octave. Each successive (lower frequency) octave 
contains twice as many data samples in both its one-shot and repeat parts. One of these two parts 
can be empty across all octaves. 


Note: Most audio output hardware and software has limitations. For example the Amiga computer 
has sound hardware that requires that all one-shot and repeat parts have even numbers of samples. 
Amiga sound driver software should adjust an odd-sized waveform, ignore an odd-sized lowest 
octave, or ignore odd 8SVX FORMs altogether. Some other output devices require all sample sizes 
to be powers of two. 


The field samplesPerHiCycle tells the number of samples/cycle in the highest frequency octave 
of data, or else 0 for "unknown". Each successive (lower frequency) octave contains twice as many 
samples/cycle. The samplesPerHiCycle value is needed to compute the data rate for a desired 
playback pitch. 


Actually, samplesPerHiCycle is an average number of samples/cycle. If the one-shot part 
contains pitch bends, store the samples/cycle of the repeat part in samplesPerHiCycle. The 
division repeatHiSamples/samplesPerHiCycle should yield an integer number of cycles. 
(When the repeat waveform is repeated, a partial cycle would come out as a higher-frequency cycle 
with a "click”.) 


More limitations: some Amiga music drivers require samplesPerHiCycle to be a power of 
two in order to play the FORM 8SVX as a musical instrument in tune. They may even assume 
samplesPerHiCycle is a particular power of two without checking. (If samplesPerHiCycle 
is different by a factor of two, the instrument will just be played an octave too low or high.) 


The field samplesPerSec gives the sound sampling rate. A program may adjust this to achieve 
frequency shifts or vary it dynamically to achieve pitch bends and vibrato. A program that plays a 
FORM 8SVxX as a musical instrument would ignore samplesPerSec and select a playback rate 
for each musical pitch. 


The field ctOctave tells how many octaves of data are stored in the BODY chunk. See "Data 
Chunk BODY", below, for the layout of the octaves. 


The field scompression indicates the compression scheme, if any, that was applied to the entire 
set of data samples stored in the BODY chunk. This field should contain one of the values defined 
above. Of course, the matching decompression algorithm must be applied to the BODY data before 
the sound can be played. (The Fibonacci-delta encoding scheme sCmpFibDelta is described in 
Appendix C.) Note that the whole series of data samples is compressed as a unit. 


The field volume gives an overall playback volume for the waveforms (all octaves). It lets the 
8-bit data samples use the full range -128 through 127 for good signal-to-noise ratio. The playback 
program should multiply this value by a "volume control" and perhaps by a playback envelope (see 
ATAK and RLSE, below). 


IFF Specification: 8SVX 421 


Recording a one-shot sound. To store a one-shot sound ina FORM 8SVX, set oneShotHiSamples 
= number of samples, repeatHiSamples = 0, samplesPerHiCycle = 0, samplesPerSec = 
sampling rate, and ctOctave = 1. Scale the signal amplitude to the full sampling range -128 
through 127. Set volume so the sound will playback at the desired volume level. If you set the 
samplesPerHiCycle field properly, the data can also be used as a musical instrument. 


Experiment with data compression. If the decompressed signal sounds OK, store the compressed 
data in the BODY chunk and set sCompression to the compression code number. 


Recording a musical instrument. To store a musical instrument in a FORM 8SVX, first record or 
synthesize as many octaves of data as you want to make available for playback. Set ctOctave to 
the count of octaves. From the recorded data, excerpt an integral number of steady state cycles for 
the repeat part and set repeatHiSamples and samplesPerHiCycle. Either excerpt a startup 
transient waveform and set oneShot HiSamples, orelse set oneShotHiSamples to 0. Remember, 
the one-shot and repeat parts of each octave must be twice as long as those of the next higher octave. 
Scale the signal amplitude to the full sampling range and set volume to adjust the instrument 
playback volume. If you set the samplesPerSec field properly, the data can also be used as a 
one-shot sound. 


A distortion-introducing compressor like sCmpFibDelta is not recommended for musical instru- 
ments, but you might try it anyway. 


Typically, creators of FORM 8SVX record an acoustic instrument at just one frequency. Decimate 
(down-sample with filtering) to compute higher octaves. Interpolate to compute lower octaves. 


If you sample an acoustic instrument at different octaves, you may find it hard to make the one- 
shot and repeat waveforms follow the factor-of-two rule for octaves. To compensate, lengthen an 
octave’s one-shot part by appending replications of the repeating cycle or prepending zeros. (This 
will have minimal impact on the sound’s start time.) You may be able to equalize the ratio of 
one-shot-samples to repeat-samples across all octaves. 


Note that a "one-shot sound" may be played as a "musical instrument” and vice-versa. How- 
ever, an instrument player depends on samplesPerHiCycle, and a one-shot player depends on 
samplesPerSec. 


Playing a one-shot sound. To play any FORM 8SVX data as a one-shot sound, first select an octave 
if ctOctave > 1. (The lowest-frequency octave has the greatest resolution.) Play the one-shot 
samples then the repeat samples, scaled by volume, at a data rate of samplesPerSec. Of course, 
you may adjust the playback rate and volume. You can play out an envelope, too. (See ATAK and 
RLSE, below.) 


Playing a musical note. To play a musical note using any FORM 8SVX, first select the nearest 
octave of data from those available. Play the one-shot waveform then cycle on the repeat waveform 
as long as needed to sustain the note. Scale the signal by volume, perhaps also by an envelope, 
and by a desired note volume. Select a playback data rate s samples/second to achieve the desired 
frequency (in Hz): 


frequency = s / samplesPerHiCycle 
for the highest frequency octave. 


The idea is to select an octave and one of 12 sampling rates (assuming a 12-tone scale). If the 
FORM 8SVX doesn’t have the right octave, you can decimate or interpolate from the available data. 


422 Amiga ROM Kernel Reference Manual: Devices 


When it comes to musical instruments, FORM 8SVX is geared for a simple sound driver. Such 
a driver uses a single table of 12 data rates to reach all notes in all octaves. That’s why 8SVX 
requires each octave of data to have twice as many samples as the next higher octave. If you restrict 
samplesPerHiCycle to a power of two, you can use a predetermined table of data rates. 


Optional Text Chunks NAME, (c), AUTH, ANNO 
Several text chunks may be included in a FORM 8SVX to keep ancillary information. 
The optional property "NAME" names the voice, for instance "tubular bells". 


The optional property "(c) " holds a copyright notice for the voice. The chunk ID "(c) " serves as 
the copyright characters "©". E.g., a "(c) " chunk containing "1986 Electronic Arts" means "© 
1986 Electronic Arts". 


The optional property "AUTH" holds the name of the instrument’s "author" or "creator". 


The chunk types "NAME", "(c) ", and "AUTH" are property chunks. Putting more than one NAME 
(or other) property in a FORM is redundant. Just the last NAME counts. A property should be 
shorter than 256 characters. Properties can appear in a PROP 8SVX to share them over a LIST of 
FORMs 8SVX. 


The optional data chunk "ANNO" holds any text annotations typed in by the author. 


An ANNO chunk is not a property chunk, so you can put more than one in a FORM 8SVX. You 
can make ANNO chunks any length up to 23 - 1 characters, but 32767 is a practical limit. Since 
they’re not properties, ANNO chunks don’t belong in a PROP 8SVX. That means they can’t be 
shared over a LIST of FORMs 8SVX. 


Syntactically, each of these chunks contains an array of 8-bit ASCII characters in the range 
(SP, hex 20) through """ (tilde, hex 7F), just like a standard "TEXT" chunk. [See "Strings, String 


ott 


chunk’s ckSize field holds the count of characters. 


#define ID NAME MakeID(‘N’, 'A’, 'M’, ‘E*) 


/* NAME chunk contains a CHAR[], the voice’s name. x/ 
define ID Copyright MakeID(’(’, 'c’, ’)’, ' ") 
/* “(c) ™" chunk contains a CHAR[], the FORM’s copyright notice.*/ 


#define ID AUTH MakeID(’A’, 'U', 'T’, ‘H’) 
/* AUTH chunk contains a CHAR[], the author’s name. x/ 


#define ID_ANNO MakeID(’A’, ‘'N’, 'N’, '0°) 
/* ANNO chunk contains a CHAR[], author’s text annotations. */ 


Remember to store a 0 pad byte after any odd-length chunk. 


Optional Data Chunks ATAK and RLSE 


The optional data chunks ATAK and RLSE together give a piecewise-linear "envelope" or "amplitude 
contour". This contour may be used to modulate the sound during playback. It’s especially useful for 
playing musical notes of variable durations. Playback programs may ignore the supplied envelope 
or substitute another. 


IFF Specification: 8SVX 423 


#define ID_ATAK MakeID(‘A’, ‘'T’, ‘A’, ‘K’) 
#define ID _RLSE MakeID(’R’, 'L’, 'S’, 'E’) 


typedef struct { 
UWORD duration; /* segment duration in milliseconds, > 0 */ 
Fixed dest; /* destination volume factor x/ 
} EGPoint; 


/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope.*/ 


/* The envelope defines a function of time returning Fixed values. It’s * 
* used to scale the nominal volume specified in the Voice8Header. */ 


To explain the meaning of the ATAK and RLSE chunks, we’ll overview the envelope generation 
algorithm. Start at 0 volume, step through the ATAK contour, then hold at the sustain level (the last 
ATAK EGPoint’s dest), and then step through the RLSE contour. Begin the release at the desired 
note stop time minus the total duration of the release contour (the sum of the RLSE EGPoints’ 
durations). The attack contour should be cut short if the note is shorter than the release contour. 


The envelope is a piecewise-linear function. The envelope generator interpolates between the 
EGPoints. 


Remember to multiply the envelope function by the nominal voice header volume and by any 
desired note volume. 


Figure 1 shows an example envelope. The attack period is described by 4 EGPoints in an ATAK 
chunk. The release period is described by 4 EGPoints in a RLSE chunk. The sustain period in the 
middle just holds the final ATAK level until it’s time for the release. 


sia! IN 


ATAK sustain RLSE 


Note: The number of EGPoints in an ATAK or RLSE chunk is its ckSize / sizeof (EGPoint). 
In RAM, the playback program may terminate the array with a 0 duration EGPoint. 


Issue: Synthesizers also provide frequency contour (pitch bend), filtering contour (wah-wah), 
amplitude oscillation (tremolo), frequency oscillation (vibrato), and filtering oscillation (leslie). 
In the future, we may define optional chunks to encode these modulations. The contours can 
be encoded in linear segments. The oscillations can be stored as segments with rate and depth 
parameters. 


Data Chunk BODY 
The BODY chunk contains the audio data samples. 
#define ID BODY MakeID(’B’, ‘0’, 'D’, ‘Y") 


typedef character BYTE; /* 8 bit signed number, -128 through 127. */ 
/* BODY chunk contains a BYTE[], array of audio data samples. x/ 


424 Amiga ROM Kernel Reference Manual: Devices 





The BODY contains data samples grouped by octave. Within each octave are one-shot and repeat 
portions. Figure 2 depicts this arrangement of samples for an 8SVX where oneShotHiSamples = 
24, repeatHiSamples = 16, samplesPerHiCycle = 8, and ctOctave = 3. The major divisions 
are octaves, the intermediate divisions separate the one-shot and repeat portions, and the minor 
divisions are cycles. 


oO r | one-shot repeat one-shot 





hi octave mid octave low octave 


In general, the BODY has ct Octave octaves of data. The highest frequency octave comes first, 
comprising the fewest samples: oneShotHiSamples + repeatHiSamples. Each successive 
octave contains twice as many samples as the next higher octave but the same number of cycles. The 
lowest frequency octave comes last with the most samples: 2°°“ve-!_* (oneShotHiSamples + 
repeatHiSamples). 


The number of samples in the BODY chunk is 
(2° + ... + 2aOcuve-1_) * (oneShotHiSamples + repeatHiSamples) 


Figure 3, below, looks closer at an example waveform within one octave of a different BODY chunk. 
In thisexample, oneShotHiSamples / samplesPerHiCycle = 2 cycles and repeatHiSam- 
ples / samplesPerHiCycle = 1 cycle. 





repeat 


To avoid playback "clicks" the one-shot part should begin with a small sample value, and flow 
smoothly into the repeat part. The end of the repeat part should flow smoothly into the beginning 
of the next repeat part. 


If the VHDR field scompression # sCmpNone, the BODY chunk is just an array of data bytes 
to feed through the specified decompresser function. All this stuff about sample sizes, octaves, and 
repeat parts applies to the decompressed data. 


Be sure to follow an odd-length BODY chunk with a 0 pad byte. 


IFF Specification: 8SVX 425 


Other Chunks 


Issue: In the future, we may define an optional chunk containing Fourier series coefficients for a 
repeating waveform. An editor for this kind of synthesized voice could modify the coefficients and 
regenerate the waveform. 


See the IFF Registry and the Third-Party Specification section for details on additional 8SVX 
Chunks such as CHAN, PAN, SEQN and FADE. 


Appendix A. Quick Reference 
Type Definitions 


#define ID _8SVX MakeID(’8’, ’S’, ‘V’, ‘X') 
#define ID_VHDR MakeID(’V’, 'H’, 'D’, 'R’) 


typedef LONG Fixed; /* A fixed-point value, 16 bits to the left of * 
the point and 16 to the right. A Fixed isa * 

number of 2°16ths, i.e., 65536ths. x/ 

#define Unity 0x1l0000L /* Unity = Fixed 1.0 = maximum volume */ 
/* sCompression: Choice of compression algorithm. */ 
#define sCmpNone 0 /* not compressed */, 
#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */ 
/* Can be more kinds in the future. */ 


typedef struct { 
ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */ 
repeatHiSamples, /* # samples in the high octave repeat part */ 
samplesPerHiCycle;/* # samples/cycle in high octave, else 0 */ 


UWORD samplesPerSec; /* data sampling rate */ 
UBYTE ctOctave, /* # octaves of waveforms */ 
sCompression; /* data compression technique used */ 
Fixed volume; /* playback volume from 0 to Unity (full = 
* volume). Map this value into the output * 
* hardware’s dynamic range. */ 


} Voice8Header; 


#define ID_NAME MakeID(‘N’, ‘A’, ‘M’, ‘'E’) 
/* NAME chunk contains a CHAR[], the voice’s name. */ 


#define ID Copyright MakeID(’(’, ‘’c’, ')’, ’ °) 
/* "(c) ™ chunk contains a CHAR[], the FORM’s copyright notice. */ 


#define ID_AUTH MakeID(’A’, 'U’, 'T’, ‘'H’) 
/* AUTH chunk contains a CHAR[], the author’s name. */ 


#define ID_ANNO MakeID(‘A’, ‘N’, ‘N’, '0°) 
/* ANNO chunk contains a CHAR[], author’s text annotations. a 


#define ID_ATAK MakeID(’A’, ’T’, ‘A’, 'K’) 
#define ID_RLSE MakeID('R’, ’L’, ’S’, 'E’) 


typedef struct { 
UWORD duration; /* segment duration in milliseconds, > 0 */ 
Fixed dest; /* destination volume factor */ 
} EGPoint; 


/* ATAK and RLSE chunks contain an EGPoint[],piecewise-linear envelope. */ 
/* The envelope defines a function of time returning Fixed values. It’s * 
* used to scale the nominal volume specified in the Voice8Header. */ 


#define ID BODY MakeID(’B’, '0’, 'D’, ‘Y’) 


typedef character BYTE; /* 8 bit signed number, -128 through 127. */ 
/* BODY chunk contains a BYTE[], array of audio data samples. x/ 


426 Amiga ROM Kernel Reference Manual: Devices 


8SVX Regular Expression 


Here’s a regular expression summary of the FORM 8SVX syntax. This could be an IFF file or part 
of one. 


8SVX = "FORM" #{ "8SVX" VHDR [NAME] [Copyright] [AUTH] ANNO* 
[ATAK] [RLSE] BODY } 

VHDR = "VHDR" #{ Voice8Header } 

NAME = "NAME" #{ CHAR* 

Copyright::= "(c) " #{ CHAR* } [0] 

AUTH ::= "AUTH" #{ CHAR* } [0] 

ANNO = "ANNO" #{ CHAR* } [0] 

ATAK = “ATAK" #{ EGPoint* } 

RLSE = "RLSE" #{ EGPoint* } 

BODY = "FORM" #{ BYTE* } [0] 


The token "#" represents a ckSize LONG count of the following {braced} data bytes. E.g., a 
VHDR’s "#" should equal sizeof (Voice8Header). Literal items are shown in "quotes", [square 
bracket items] are optional, and "*" means 0 or more replications. A sometimes-needed pad byte is 
shown as "[0]". 


Actually, the order of chunks in a FORM 8SVX< is not as strict as this regular expression indicates. 
The property chunks VHDR, NAME, Copyright, and AUTH may actually appear in any order as 
long as they all precede the BODY chunk. The optional data chunks ANNO, ATAK, and RLSE 
don’t have to precede the BODY chunk. And of course, new kinds of chunks may appear inside a 
FORM 8SV*xX< in the future. 


Appendix B. 8SVX Example 


Here’s a box diagram for a simple example containing the three octave BODY shown earlier in 
Figure 2. 


*8SVX’ 
‘VHDR’ 20 
24, 16, 8, 10000, 3, 0, 1, 0 


‘NAME’ 11 


‘bass guitar’ 


0 
‘(c) / 20 


1985 Electronic Arts 


‘BODY’ 280 





The "0" after the NAME chunk is a pad byte. 


IFF Specification: 8SVX 427 


Appendix C. Fibonacci Delta Compression 


This is Steve Hayes’ Fibonacci Delta sound compression technique. It’s like the traditional delta 
encoding but encodes each delta in a mere 4 bits. The compressed data is half the size of the 
original data plus a 2-byte overhead for the initial value. This much compression introduces some 


distortion, so try it out and use it with discretion. 


To achieve a reasonable slew rate, this algorithm looks up each stored 4-bit value in a table of 
Fibonacci numbers. So very small deltas are encoded precisely while larger deltas are approximated. 
When it has to make approximations, the compressor should adjust all the values (forwards and 


backwards in time) for minimum overall distortion. 


Here is the decompressor written in the C programming language. 


/* Fibonacci delta encoding for sound data. */ 
BYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21}; 


/* 
* 
* 
* 


Unpack Fibonacci-delta encoded data from n byte source buffer into 
2*n byte dest buffer, given initial data value x. It returns the 
last data value x so you can call it several times to incrementally 
decompress the data. */ 


short DlUnpack(source, n, dest, x) 


BYTE source[], dest[]; 
LONG n; 

BYTE x; 

{ 

BYTE d; 

LONG i, lim; 


lim = 5 <<. 1; 
for (i = 0; i < lim; ++i) 
{ /* Decode a data nibble; high nibble then low nibble. */ 


d = source[i >> 1]; /* get a pair of nibbles */ 
if (i & 1) /* select low or high nibble? */ 
d &= Oxf; /* mask to get the low nibble */ 
else 
ad >>= 4; /* shift to get the high nibble */ 
x += codeToDelta[d]; /* add in the decoded delta x/ 
dest[i] = x; /* store a 1l-byte sample */ 


return (x); 


} 


Unpack Fibonacci-delta encoded data from n byte source buffer into 
2*(n-2) byte dest buffer. Source buffer has a pad byte, an 8-bit 
initial value, followed by n-2 bytes comprising 2*(n-2) 4-bit 
encoded samples. */ 


void DUnpack(source, n, dest) 


BYTE source[], dest[]; 
LONG n; 


D1lUnpack (source + 2, n - 2, dest, source[1]); 


} 


428 Amiga ROM Kernel Reference Manual: Devices 


IFF FORM and Chunk Registry 


This section contains the official list of registered FORM and Chunk names that are reserved and 
in use. This list is often referred to as the 3rd part registry since these are FORM and Chunk types 
created by application developers and not part of the original IFF specification created by Electronic 
Arts and Commodore. 


For all FORM and Chunk types that are public, the official specifications from the third party 
company are listed (in alphabetical order). At the end of this section are additional documents 
describing how the ILBM FORM type works on the Amiga. 


New chunks and FORMS should be registered with CATS US, IFF Registry, 1200 Wilson Drive, 
West Chester, PA. 19380. Please make all submissions on Amiga diskette and include your address, 
phone, and fax. 


IFF Specification: FORM and Chunk Registry 429 


(suoZTIOH MON) JeuUTOF QuewmMoop SE 7TIMCITd 
qemrozy ceptA exnteqd eyeatid 

eoTOA DeW NInyn pearesez ¢g JAI Wa 

ezoDs ninyn pearesez ¢g JdaI Wa 

dozd euweu zesn peazesez ¢g ddI Wa 
(estndur) zeaTTs oqany ‘eqep butzepuez d-¢ 
seTboTouyqoey buybrey Aq peazesexz 

zeayip we sks IGIN UeTTerzqyTT TeqseW ysendpunos 
wroy ez0Ds oTsnu eTduts sg JAI Wa 
(eqeatad) weyuog Arey Aq peazesey 
(eqeatzd) wequog Azep Xq peazesey 

qeuroz ezeedsexyeys eqeatid 

(ae-3dtnos) qeuzoz eueds oQeatid 

qeuzoz punos petdues 

wroF uoTqeuTUe eQeaTtad 

peazesez AT tzez0due 

(estndur) xeaTTs oqany, ‘swuzoz ebeut go 
(STQeTTeae Jou yemTos) adu 3TI-P 


pearzesez AT tzez0duweq 

(@4nAQFAsUL SWS) JeEWTOF ETTF yored 

(wa) wxz0z eaou eatqoedszed aI jutedd 
xzeTsTauept dnozb sg gal wa 

eueU eAeETOSGo peazesex Gg JAI Wa 

erznqotTd qsoquyoeW pearesez cg adI Wa 
(@4nQTAsUL SYS) yoeqeoexry werborg 

dozd umu [e}Tres pearesexr Gg JAI Wa 

dozd wezhozd peazesez ¢g ddI Wa 

dozd zosses0zd peazesex ¢g ddI Wa 

dozd zeqjnduod peazesez ¢g ddI Wa 

(HqUD uesneyxD09g) eouenbes [eoTzeuNN 
(seeg weAeS - UOTSTAUREN) eberojs ejep TeOTTeUMN 
peazesez AT trex0due 

qeurozy x-oTsnW eQeatid 

qeuroy ejeatiad - IAOW LSIT 

ubStseq umoitD 

xetzTauepy dnozb ¢g aaI Wa 

peazesex 

ezemqyjos seeg uesaes Aq peazesex 

(SZWO 3083U0D) uoTZeuz0zur dewata pepue7xe 
uoftqsebhns xunyo sheq epoumety 

(peazesexz AT yzrezodweq) deur Aouezedsuezy 
yunyo ydtzosqs0g peqetnsdeoug 

(wa) yunyo eToAD zoTOD peoueyue AI QUTedd 
(wa) yunyo eatTqoedszed juteaa 

yunyo qout zed s30g 

yunyo metATSta yeAMen eQeatad 

peazesex 

syunyo zoToo wey ofureuMq ye MeN 

(SZ¥O 30e83u0D) (xTboT-3z0s) yunyo Hbuyueu roTOD 
(SEWO 30RQU0D) dewo yOeRTA 3 ‘MOTTEX ‘equebew ‘ueXD 
yunyo eTqey dnyooy zr0TOD 

yunygo Auyed wojoyg eqeatad 

(sueezos) yunYyo quTed uojoyd eqeatid 
(seysnzq) yunyo juTed uojoyg eqeatid 
yunyqo uotjeottdde sasy ejeatad 

xeqteH Aq peazesexz 

xeqten Aq pearesex 

wroz deujyq zejsez Gg ddI Wa 

BSIBMAJOS SUOCZTIOH MON - MOTT 

(eqeatzd) Tesodozd ebexr0js eoezrequy resn 
ezoos ofTsnu ‘ueh peazesex Gg AAI Wa 
(peaybtzAdoo) jTesodozd ebexzojs euetdeziq 
wurOsF 3XeQ pea euros Se AAI WA 


4sibey yuNYD pue wo0d Jl 


Dop  daomM 
oagda 

XOAN 

wosn 

AYNO 

>op* dadL 
qqoL 

HBAS 

saws 

MOHS 

TOHS 

MWHS 

aeos 

Dop’ dvvs 
NXOUW 

xaou 

Dop° saqdSu-Nddu 
vaou 

wAdwad 

LXLd 

HOLd 

Dop’ dsud 

doud 

wald 

sold 

pop" adLdd 

NSO 

wWdoO 

addo 

doo 

OaSN 

DOP" XaLWN 
answ 

XOSN 

TAOW 

IqIn 

LSIT 

TALI 

£aor 

Dop* INGX “NETL 
jesodozd *owLA’ WaTI 
aWAL “Wa TI 
Sop’ isda" WaTI 
Dop*ONud WaTL 
Dop *Addd "Wa TI 
Dop "Idd" Waitl 
MASDC WETI 
ALOG° WaTI 
Dop* dA THLO “NETI 
DOp "WYNO "WaTI 
DOP “MAW “WATI 
Dop* LANTOS "WaTIL 
WsHd Watt 
dOued “WATI 
Wad “WaTI 
Sas¥  NaTL 
wade “WTI 
Wode ‘Wa Tl 
WaT 

Dop "dwal 
yesodozd- rns 
woss 
yesodozd: qxup 
IXLI 


zeTztquepyt dnozh sg aaI wa Waod 

quoy 1oADeA TOF peaTesEI Gg AAI WA ALNG 

quoj teqser TOF peazeser GB 4dI VG WING 

peazesez - CEpTA eExnTed wld 

qeurey eTAOU UOTSTARQUeT Dop* INVA 

06/zt ‘ssetxkeg utc Aq peazesox swid 

qeumzoz prepueqs yoelqo d-z Dop*azada 

oquep sotuozyzeAoUL Tox AeWIOZ eQeatad yoga 

eTTZ eaznqotd mez ALOG - ALOG ALOG 

eqqeted quted aLod - vaod waoa 

dtto quted azod - Tod Tooa 

(Tenueu ATEeYR UT Sop) ASeYeWQUCY, Teuocszreg oVUeOCTD Wado 
pzeoqdt[> ut sqeumoz snoTzeA pToy O73 dITO Lwo alto 
(Aysqtaeqy ofzg Aq peazesexz euweu) deuytq AyunyD WaHO 
xetztquept dnoxz6 sg adI Wa Ivo 

yeuroz eqeatid etTeqI OAUEBOTO ooTo 

ezemqjos xueTeyd ‘rr ‘epneujzed’g ‘eseqeqed sad asad 
dump xesdg IdIW uetTrerqT1/109;pg ysenbpunos ¢MNVE 
(peseetez yeh jou Aewrosy) squeae uoTtsTAebtuy ---- AGA 
(peseetez 304 Qou euros) spueumoo uotstp~eh Tuy ---- ODAW 
dL 4aI DOP" JOAW 

(peseetexz 3eX jou jewroz) moTz uotetAebtuy ---- JOAW 
peazesez At Ttzexz0dueq ---- IXxXLy 

(64) pezeqstbezun T=2> sTaw 

(pto) Tesodozd yeuroz eatyore sodozd tesodozd‘ouw 

suotjeutuy (de) cezeq3g dL_dal oop’ 9do*wINW 

wzoy uotzeurue TSO di_diI Dop *WINW 

euros ysniq WINWY dil_diI pop“ ysniq WINW 

(CePTA exnTeq ‘Zeurezg) wroz deuytq pejewtuy dLb_diI Dop ‘WENY 
(ora etyquds ‘rretddy‘oew) setdues 31q z7E-T OTpNW dL aaI pop’ aaIv 
(464) pezeqstbezun ss== WHY 

wxozy dew3tq snonbtquop ebtuy di_daI Dop *WHOw 

wzoz xASe oz syunyo Bbutdoot aL dal Dop gawd “NOgS "xXAss 

wares XAS8 ZOF syuNYo oereAS dL AAT DOp "NWd°NWHO” XAS8 

wroz etdues punos 34Tq-8 $8 ddI Wa daI_Wa xass 

yunyo 3xeq qybtzkdop otzeuep cg ddI Wa JdI_Wa (>) * (Aue) 

yunyoS 4x03 ITOsW peyqewzosun oTzeueD G8 ddiI WA JdI_Wa Ixgi* (Aue) 
yunyo "oJe ‘oFsnu ‘Are FO SUEN OTTeUeD G8 MAI WA dJdI Wa gaun’ (Aue) 
(OJUF TOF SLWO FOe!QUOD) UOTIeOTFTAUeCI AUTTIION a= Sop aItH’ (Aue) 
STTZ ddI ue Jo butz3s NOISUBA 0°% 20F YuNYo db_AdI op" ugaAa’ (Aue) 
yes zeqoezeyo BHButAztoeds zoy yunyS dL dal pop‘ Laso’ (Aue) 

yunyo buyrzys zeqoezeyo otreuep $e ad WE daI_Wa SUHo* (Aue) 

yunyo zoyagny oTreueD Gg 4aI WE ddI_Va Hiay’ (Aue) 

yunyS uotzejouuy oTreUueD Gg aaI Wa ddI Wa ONNW* (Aue) 


‘xez pue ‘euoyd ‘ssezppe znoA epntout pue eqjexstp ebtuy uo 
SUOTSSTWQNS TTS SXEWU VseOTT “OSE6T “Wd ‘TOEASEYD 3SEM “OATIC UOSTTM 0OZT 
‘Kzystbeq agdI ‘SN SLYO U3tM pezeqstber eq pTNoys sWYoOd pue syxuNYyoO MON 


*suotqeotzytoeds peseeTerun 
qeX se zo eqeatad ooze , YRTM pexzeu sueqAt puy ‘“ejeatad eze yotym Jo 
euos ‘SLYD 03 peqqtuqns ueeq eaey yotymM sTesodoid eze ,sodoid, pexyrew sueqr 

“uoTqDes sTYR eYA UF peqTzosep ere ,SOTdS dL, _peyzeu esoy, “soeds gdI wa ou? 
jo szeqdeyo utew ey3 ut peqtiosep ere ,ZaI Wa, pexzeu sueqjl “punozy aq Xeu 
YUNYO TO WAOA SYR UO UOTReUTOFUT TeEUCTATPPe STeYM SeqTIosep wUMTOD TeqUe. eUL 


+ (euweuyUNYS*eureuurT0OZ se uMOCYS) 
swaod Bbutqstxe rox syuUNYS Meu pezeqsthbez pue ‘ (eureuxunyo’ (Aue) se umoys) 
syunyo ofzeueh ‘swyod pezeqstbexz Jo AstT TeoTjeqeydte ue st HutMoTTOS euL 


Azystbeu yunyO puw Wuod AdI 


WSibey yUNYD pue WHOF JI 





Devices 


430 ROM Kernel Reference Manual 


Zp Le Bopteqes* youeqyzrom :ugAs 
:etduexg 


T° LE Se YONS uoTsTAeT/UOCTSIEA e ST AET"TEA pUe 
SITS SYR FO TOTFTRUSEPT ZO oueU SYA st ,,oUreU, STEYM 


AGI° ICA OCUTeU ?agAs 
-Buyz4s uotszea 0o°Z pzepueqgs upequos oj ‘Wuod Aue uy esn zoz YUNYD ¥ 
“xeFETITSL ut_zeW Aq pezeqstbey 


@TTF ddI ue Jo HutzAs NOISUHA 0°2 TOF Yunyo 


90Pp"H3A5'0000 


{ 
‘[L] peazesoy SNOT 


/» SONTEA TEUCTITPPe SUTFOP TTT WHO +/ 
/» (jeszeyo ebtuy p3s) T UTIeT WNOR=0 x/ fegepoo SNOT 


} 3eS9 AoONT4s 


“WdOd UF 4xXeR 


xoyJ pesn yes reqoezeyo Aztoeds o3 ‘WUOU Aue ut osn oF YunYyoO W 


90p 


LAS9 


‘resETTTeL uTyreW Aq pezeqstbey 


qes zeqoezeyo BHutkztoeds zoz yunyo 


0000 





IFF Specification: FORM and Chunk Registry 431 


“pIeTy cezeys eyQ uy perejueD st eTdues eyQ ’7/ARTUN = uoTATSOds FI 

*aqu6tz eyq oq Aem oyQA TTe peuued st etdues oyQ ‘Oo uotytsods JI 

“azeT aya og Aem oyQ TTe peuued st eTdwes egy ‘Aqtun uotatsods 51 
:etduexe r0g 


" »  aybtz 
SUMTOA Teuueyo AJeT ouL 


“eUMTOA ToEuUeyo AFOOT -— oeuUMTOA TTeTEAO = 
*(uotqatsods / Ajtuq) / eumtoa TTereAO = 
“yun UGHA SYR UT ezNQoONzAS 

AOPeSeP_eoton SyR UT PTETZ ,,oumToa,, eq Aq peutTurejep st eTdues eyQ Fo oumToa 
TTezeao ey, “sTeuueyo AzeT pue qyStx eyQ yIoq uo peXeTd oq ysnu eTdues oyL 


*jTeuueyo eTbuts e& TOF souMTOA ej7eTOSTp 
yo xequmu ey3 Z/T OF Tenbe st eTqeTTeae suoTyTsod oezeqjs ejeTDsTp Jo szequmu 
eUL “PTeTF cezeAs eyQ UT UoCTATsOd e seqtzosep eTqeTzea ,uCTATsSOds, SUL 


/* 


“guoTqnTosez quezeszTp FO ezempzey oTpne ueemjeq AA TtTqQeqeduiod oF MOTTE » 
03 pesn st (SNOT se peutsep# STEYMESTS) ,pEXTa, FEY SQOU SeseeTd x/ 


/* 


d umutxeu ey 03 szezez 


“sUMTOA STQTSSO 
pue ‘IQOOOT sB peut 
Fopz# ereymeste st Aatug »/ 
/x Kayun => wopqtsods => 0 x/ ‘pexta uotqzysods zepedky 
(, 1‘ uNs‘ Ws’ ds) QIOXEH NVA AI OuTzep# 
“sOeUMTOA QUeTeZFTP Ae ‘sTeuueyo omg uo ATsnoeueqrnuts eTdues 


eyq Aetdez 03 Azesseooeu st ar “ejep zo Aezze eThuts e Sutsn punos oeze34s 
e eQeer> 03 uoTREWFOsZUT AzesseoDpeu eyQ septaozd Nvd xUNYD eQep TeuoT ado eyL 


NWd yxUNYD e7eqd TeuoT {do 


90P"NVd NVHO'XAS8 


‘zeyeeds Bbhuorm oy3 03 peqnozr sTeuueYyS TeYQoUe SRedOCTTe OF IO 
‘KTuo ~euueyo etqetteae ey AeTd 03 reyQem ‘peqeDdoTTe eq 3,ue> zATed oezeqs e& 
oF TeuueYo e FT Op OF AEYM epToep of reumerHord eyA O73 AFeET st AT ‘uTeby 


“yqbuet 

ut Tenbe eq prnoys uoTZEwOZUT LHOTY pue LAAT CYL “LHOIU ey Aq pemoTTos 
‘UOFAeUTOJUT LAFZI 249 4SITZ OATFIM pTnoys eremgzos Huttdues ‘suotqueauoo 
Hutastxe oj ezeype of; “uot AewrosuyT AyHtzr pue azeT yRo0q suTequoD sated 

oezeqs zoz yunyo ACOs eUL “([e‘z] pue [T‘o] sated ebtuy) szexeeds yRoq 03 
peynoz sTeuueyo zo ated e seztnbex eTdues eyQ vey ‘omuaLs st ,edAjeTdues, Jr 


*peqeosoTTe eq jouueo ,edxjetdues, Aq pejeubtsep epts 
eyQ wo Teuueyo e usym eTdues e AetTd 09 Jou ro reyQeEYM epToep oj seumexrhord 
ey JO UOTASTOSTp ey3 OF AFET St AI “(€ Pue O sTeuUeYyo ebtuy) pepusqUT sem 
zexeeds 33eT ey ‘LagT st ,edXqe Tdwes, gr *(ebtuy eyy uo Zz pue T sTeuueyd) 

‘zeyeeds qy6tz eq 073 peynoz Teuueyo e uo Aetd of pepuequt ATTeutbtTz0 
SEM 2F 3e42 sMouX eTdues syQ SutTpeez werhord eyQ ‘LHOTU st ,.edXkqe tdures, JI 


JonoT edXkjeTdues yopedX3 
(uN. / Ms sHs' 10.) QTOXEW NWHD GI SuTsFepH 


19 OFUILS SUTFOPH 
Te LIFT sutsop# 
‘Tp LHOIY eutzep# 


“spunos 

petdues go yoeqheTd zo butpzopexz oexzeys SutAotdue swezhord zoz [nzesn eq PTNOM 
yunyo sty, ‘sTeuueyo Fo uoTQeuTquOD ro ‘Teuueyo petstoeds e uo eTdures 

e Ketd 09 Azesseooeu votqzewrosut eyq saath NYHD yUNYD ejep Teuotydo eyL 


“Katttqeqeduos utequyeuw oj peqtutyT eroyezey 
ST erey uoTAeQuUeUeTdWT sqt ‘seTdues eseyQ peor AQtTTQe eyA UTeQUTEeU 
oL ‘ze Tdures oezeqs zetndod e zoz ezemagzos ey Aq ueqqtzm Apeezte st yunyo sTyL 


NWHO yUNYD eQeq TeuoT Ado 


*qDez eyQ TeQze soTAsTreqQoeTeYoO 

oezejs ueath setdues y4tM Nyd pue ‘oezeqs ut peTdues spunos yqTM sTeep 

NYHOD ‘N¥d PuUe NYHO ‘syunyo eqep Teuotqdo omg eze moTeq peonporzquI ‘sueqsis 
(pzepueqs-uou) Butqastxe yata Aqrttqtqeduop Hututeqjez ettym ‘ATQueqstsuoco 
sty3 Butop zo Aem e optaozd st 03 03 petra evAey I WeUM “pzepuejs 

go odXq Aue 03 Bbutzeype ATnz3 ouou ‘ebtuy ey uo pequeuerdut ATquezznd 

styy Bbutrop xox spoyjeu zo zequmu e ATAQuezinS eze ezeyq ‘ATeqeunQTOsUN “pTETs 
oere4s eYW UT UOCTATSOd eqnTosqe ue eTduwes ey seath sty, “seumjToa AuezezZzTp 
Qe sTeuueyS QUeTezZzZTpP OMA UO UOTREWTOFUT TeOTQUepT eyQ sAeTd punos ocereys FO 
edkj puoses ey, ‘eumtoa oures oy 07 Jes Oq QsnU sTeUUeYS yQOq ‘buTbeut oeze qs 
eyq Sututequtew eTtym etdues go ed&q styq yoreq Aetd of “sqnduyt 3zeT 

pue 3y6tz butsn ‘ATsnoeueqtnuts peztTyThStp eze seTdures juerezztp omy : ze Tdues 
oezejs © YATM peqeezo buteq punos Teutht10 eyA uo setter ysatF SeyL “punos 
peztathtp e yoeq Sutketd ueym GHutbewt oereqs ejeetD 03 sXem omQ ore erEYL 


‘OUI ASTa PTOD ‘seuoc ptaeqg Aq pereystbey 


ecto, eTdueg 3tq-g ddI .XAS8., S43 UT BuTbeut oeze3s 
syxuNnYD NWd'SOWS PUe NWHO’ SONS 


wires XAS8 ZOF sZUNYyo os8r94S 


90P’NVd NVHO'XAS8 





Devices 


432 ROM Kernel Reference Manual 


(UN, ',0,'.3.'.S,)QIOXEN NOUS AI eutyzep# 


“Kisnoeueyrnuys ejep 3yHtz eyy uy uopytsod e7Xq y300F EUR pUe 

eqep 3FeT eyy ut woTyTsod e3Aq qR00F EUR 3e punos eYyR QreQs NOA ‘wroyeAeM 
oeze3s © UTYUATM OOP WOTReSCT Qe sqzeqs dooT e& Ft ‘spOM TeEYRQO UL * Ken 

eues eyq ATQOexe UT sUOTQEDOT pue senTea eYyR AeezrQ ‘oCeTERS ST Wroyeaem CYR ZI 


"peubTTe GYOMONOT eq 
Ptnoys doot zo queuhes yore Jo pue pue 4ITeAS EYQ FO sSUOTIESOT EYR TEequeUSY 


‘(omagzis 3+ z Aq peptatp) aaduet xqod eya Tenbe prnoys setduestHjeedez ey, pue 
0 03 30S eq PTNoYS seTduesTHROYseUO ey ‘syuNnYO NOas Bbufufequon wzozeaem e UT 


,°qefnteeceettex, ,°“qefnrTetter, 
OTOTOTOTOTOTOTO PLEAHOOO 6SPVAPZH 000E000N 80020000 00020000 80200000 


eqed ezts = ,k-d-0-4 [ g doot 1 py doot ] 


squeufes zo doot g = g / Tewtoep se 7Xq op 
v 
v 


."qeenTeTrTer, ,‘qeCnteTTeeeeq, ,°“yefnTeTTeeeer, v 


Vv 
000Z0000 802900000 005900000 00000000 00500000 00000000 82000000 aPTSStES 


c € doot 1c z doot 1. T doot ] [ ezts ) JN-3-a-s, 


“**stqQ SXTT FOOT aqbTu eTTz e& UT eyep MET SOUL 


*sdoot g stenbe *- (g / oF) = sdoot Jo zequmu "** Op == eZzTs yuNnYo FF “Bg 
-g Aq ezts yunyo NOaS 
eq3 eptatp Atduts ‘eTtzy weatTb e ut suotytutzep doot Auew moy eutuzejep of; 


“(py Aq etqestatp) peubtTe GYOMONOT 

eq Asnu seNTeA FO sUOTReSOT EYL “WroFeEAeM GYR FO ATLAS SYR WOTF sSQOEsFFZO OTe 
YOTYM suoTATUTFep ,pue, pue ATVs dooT, ONOIN JO sated Fo sysTsuod ASTT STIL 
“ASTI 243 UT EDTMA sINDDO UOTATUTJEp eqy 

‘eDTMQ Qeedex queubes e eaey oL “sxDOTq peuTyep Jo eouenbes e ut oTdues 

e Ketd 03 Azesseoeu uopyeurosuy eyA seaTh NOgS yUNYS eqep Teuotado eyL 


NOaS YUNYD e3eq TeUCTIdo 


“**suoFatuyzed yzUNYD 


90p"3d0Vs'NOAS XAS8 


*peztnbex Axzouweu sseT reZ YRTM 
Teut6tx0 eyQ se owes o4Q ATQOexXe punos of epeU eq wed ebessed oyq ‘suotqtsod 
doot etdyatau ey Fo Huy {ype Tnyezed YATM “pesocuter eq UeD AOWdS Awad SUL 


[ eveds peed ) eoeds peog 
gdoot J 
[ pdoot ] 
[ ¢doot ] 
[ zdoot ] 
C Tdoot ] 
-yeeee(ntessetTen’ “yefntTeTtTen’ “gefnteTten’ * “yefnreTrTeeeeq’ -* “yefnteTTeeeey 


“SMOTTOZ SB YOOT pTnom Huypzopez eaoge eyQ 03 eouenbes e burktddy 


» qeeeefnpoooerTeq’ “yelnteTTen’ ‘qe(ntetTen’ ~ “qeCnteTTeeeey: -* “yeCnToTTeeeen, 
TIaNNXa 


+Kzowew ut pezojs wey3 eaey ueqA TeyReIT suoTQDes yeedez zeqnduos ey 3 Bbutaey Xq 
epeu eq ues shutaes TeTRUueAsqns ‘yeedex AtTdwts yotym sqzed [Texeaes ore eTeNR 
3eq7 puts prinom om ‘etduexe HutmoTToy eyy Jo Hutpzovez e& pey OM JT "Bo" 


*peaouez eq ueo pue Azessepeu eq zeHuoT ou TTTM wroseAeM OY UT peroRS 
sesnzoys BHututTeuer ey, “ews peztnbez eyA 3e snzoyo ey3 jeedez pue 
yoeq doot zeqnduop ay3 eaey 03 dn jes oq ueYyQ Ue sUOTATUTJEp FO ,SONCTAS. W 


*WIOFOEARM OYQ UT perojS 

snzoyo ey; so Adop euo eaey 09 Azesseveu ATuo st Ay ‘wroyzeaem eyQ HbuoTe sewty 
yezeaes pezojs snzoyo sTyR eaey ueYyR ZeyZez ‘/Hutpzosez e ynoyhnozyy syeedex 
snzoyD TeotTquepy we Z+ ‘eTduexe zoz sueow styL “setspoeds yunyo 

NOFS CYR QeYR Tepzo ue ut ATTeTQuenbes wrogenem oyR Fo suctyzoes AetTd TTTM 
yunyo styq sqzoddns yotym wezborzd zefeTd punos petdures e 3eY3 pepue Ut sf AI 


‘wz0seaem OMUALS XO ONOW XASS eAeQD0 eThutTs e UTYITM 
suot}0es zo sdoolt ,eTdTAINN, eUTFEp OF peqeeTD uSeSeq sey YuNYS NOUS. SUL 


-eoeds 


etdues etqentea dn Bbuyxe3 ebessed TeotTsnu zo punos reTTuTs & JO seoUeySUT 
Tezeaes buyaey wey, reqqez suotqoes yeodex zeqnduoo eyQ butaeyq Kq Xzxoueu 
eazesuoD 03 st esodaind s,31 “syunyo ejep Teuotydo Jo 3STT KAS8 SY OF PEeppe 
ueeq sey uoftjueqxe [Tnyesn e ‘D709 ,,"° snzoyD "° zesTeA “* sNnrOYyo “" TesreA, 
‘seut3 ueatTS je Qeedez yotym sebessed [Tereaes sutTequod OTsnu ue qzo eqtnb 
3eq3 pue ‘otsnu st shutpzocer eseyA Jo QueqUOD eyy ueqgzo eqTnb yeyQ Sbuyumssy 
- Xzoureu 

5]e0 OsINOD JO sTYL “punos Jo (seqhuTU weAe) spUOCDeS TeTSeAES PIODET OF YSTM 
Kepo3 etdoed Auew ‘squeumzqsut Teotsnu se osN TOF suLroOFOAeM Sutdoot yr0ys 
yo wxoz eq3 ut ATutew ezem ebyuy ey uo punos TeqThtp Fo sesn TEeTTIeS STTYUM 


-Xzouew so squnowe efny butpuewep zoz snotrojou eze seTdues punos 
“par Aja ezemqzos ueosuey ‘uewzon reqeg Aq pezeqstTbey 
eoTon eTdues 3Tq-g JdI .XAS8. O43 UT Suyouenbes dooy eTdTa1oW 


syanyo gdva pue NOgS 
wroy xASg8 zOxZ syxunyo ButdooT 


s0p"30Vs'NOAS XAS8 





FORM and Chunk Registry 433 


IFF Specification 


-sebewr ‘quteaq ‘agerotyder 
O{UtT PpeEepeoT eq ued YyoTYM ETTZ oTd WATI ue se userDs owep e sears 
(oyseqebyuy) WaTIeaes 


“eTTS OFd qewrozy WaOW ue AeTdstp pue speoT 
(oTsegebyuy) WEOYPEOT 


‘qeuzroy WHOW UT ueezDs eyQ seaes ATTeUOTIAdO 

“(sebeay ‘quteaq ‘3zyezoTydezD) eTTF Ofd WATI gaI ue sXkeTdetp pue speoT 
(oFseqebtuy) WHOWeseS-NETIPeOT 
(sxTOMQEU SNOTIeEA ‘AStP dd UsSTA STA uoos ETQeTTeEae ‘ufeuog oOFTqnd) 


TEWMLIOS ONILWOddAS 


“Stseg worzz sueers 


buyaes/butpeolT ueym peztTTeer eze seseexout peeds queotytubts ~sueldatq 
zed e3t2M/peeu sod evo y3tm sdeuytq go butxroqs/butpeoT etTqeue o; 


sesodizng yunyo 


*u euetdatq ybnozy3 0 euetTdatq zoz eqep Tet Quenbes 
suytequop yunyo ey, ‘“eQep eueTdgtq snonbtAuos suyequoo yunyo LIEw Sul 


:uofqadytzoseq yunyD 


(seuetdiia ebtuw) <Liayv aI yung 


‘seTTy Zeur0Z gar Jo AatTtqeqzod pue AatTyqTxXeTF eyQ Hututezez eT Tym 
‘oTseq worz ATTeyoedse ‘sueezos zo Hbutaes/HbuypeoT xz9ejsez ETqQeue oF 


resoding WuOd 


*(souetdzra ebtum) yunyo gray ue Aq peoetdexz st (dewatg peaeezzeqjur) yunyo 
AGOG Tewzou eyy ydeoxe WATI WHOA se QeUTOZ oues SYR Sey WEOW WOU 


ruofadtzoseq WuOd 


(dewata snonbtjuop ebtuy) Waow ‘:dI WuoOd 


Wao zeuddeyos uXkjTozreD :Aq peyatuqns 
98/6Z/SO :peas3ztuqns e7ed 


(seuetdira ebyuy) Liaw xunyo 
(dewata snonbtquop ebyuy) waow WHOd <dI yUNYD/wTOg 


NOILdIwoOsad NNAHD / WAOd ddI 
wroz deuntg snonbtquop ebtuy 


90P'WE OV 


“zeprTo AeYQ UT AGO ‘AdWa ‘NOUS ‘NVHO SAEY PTNOM suTOFOAeM 081035 


“KGO@ OY STOFEq AsSeT Eq PTNHOYs AdYA pUe AdvA erOFeq eulod pTNoys NOAS 3eq3 
qumy3 jo e[nz Tereueh e st AT ‘eoUuSeTeFZTpP Youu syeuw y,upTnoys repxo yHnoyaiw 


(.3.'.0.' 4, sd, AIOMEN AANA AI CuTzop# 


‘peyoeez st gp zequmu doot ueym BHbutpez 32e9S 


v 
D3e@ 538 TOTOTOTO TOTOTOTO PLEAHOOO 6SbPANCD az000000 70000000 SPPPTPoD 


“"eqeq ezts 1K-d-0-&, "ON doot [ ezts ] ,a-d-w-a, 


“sty EATT YooT Aew oTTZ e& ut eyep MET SUL 


“seysTUTy wWroseaem oYQ 
se jsn{ eumjoa ozez 34TY TITM YoTYM eAez e Qe uMOp SumToa eyQ Bbutddeqs utbeg 


*Hhutuypeuwer eury = 
puoves zed setdues ut eqez xoeqKeTd Quezimns eyQ 
Xq peptatp 


(se3kq ut) eouenbes quezino butpntout seouenbes Bbututewez [Te Fo yybueT 


+++ HutMoT TOF 

eUR UO peseq uOTReTNOTeS e& op prnoys ezemazos Huthetd ey, “Aetd 03 3zeoT 

euty Jo yybuet ey Aq peutuzejep st eoetTd sexe epey sty YOTYM We EeQeZ SUL 
‘utbeq prnoys eumTtoa ozez 03 buypesy ‘peyoeez st gy doo, esuo AeyR Astooeds 
TIT sp JO uoT3tuTzep gawa w “sdoot og Bbututequos wrozyeaem e evey Aeu nox *5e 


‘uybeq prnoys epezy oyQ YyoTYyM Ae requmu dooT 

ey 03 spucdsezz0D requmu sTYL “3T UT TequmU e sey YOTYM ENTeA ONOIN Suo 
JO sqstsuoo yunyo gava w ‘Aepoq seop oTsnu Tetoreumos se Aem oures oy R 
yonu ut otsnu zo eTdues e ystutz 03 eTqTssod st 3x ‘eoueTts 03 Aeme epez 
03 utbeq prnoys punos ayy zequmu doot yeym 3e seuTzJep yuNYO AdWA OGL 


gava xunyo eqeqd Teuotado 


90p'A0V4A NOAS XAS8 





Devices 


434 ROM Kernel Reference Manual. 


ezngonazys yunyYD aaI :z eaznhta 


+ 
/\ 
oOFUT Tepeey { +. 
\l 


$o--- == 


seqep Aq pemoTToy uopTjeurosut 
zZepeey eulos JO sysfTsuoD yunyYo Ww “SeTTS «SS ddI Wa. JO syootq butpttnaq 
ey} eze syunyd “eqep Jo syunyo Jo zequnu e Jo dn epew st TTF .G8 Jal Wa. UY 


»' SOTTA Reuz0g eHtueqoreQuLr 

zoZ pzepuejs /,Gg8 FAIVA., BAeumDop eyA oj rezor oseeTd ‘G8 FdI Wau FO 
UCTSsNosTp e7eTduoD ezour e Og ‘ad OTpNY OF ouEMTeEh oe 2eq G8 JAI Wan FO 
suofqiod esoyy 03 surosyu0D aaI OTpnY “seTTZ ut eqep Hutzojs rox ernjoNnIzAS 
TTereAO Ue seUTFEp ,SeTTA Yeurog ohueyorequl oF pzepuejs ,GB ddI Wain SUL 


@AN_ONAAS STTA 

“peptoae eq prnoys sebessou peqezeueh-uwerbord zo uoTjeQueuMDop TeAeT-ZesNn 

UT (nddIWn /°8°T) uotReTaerqqe reqz3QeT-ITnN0z e Aq seTTS aa OTpny 03 Hutzzeszey 
“aaI OTpny OF peqetaezqqe eq ued oeureu oyQ ‘xoq BboTetp ,°" "sw eaes, © UT SB 
yons ‘zesn e 03 WeUTOF sty A FO ouweu oyQ Quesezd oj spesu wexrbord uot ject Tdde 
ue JI ‘“Qewzog eTty ehueyorzequl otpny st prepueqs sty TOF oureu TeTOTFFO ouL 
JiII ofpny og butzzezey 


sqeuroz efez0js eqep adI 71 eznbtaZ 


:zeyo 


izeyo 
oT @ € @’ S&S 9 Lb 
I SMOTTOZ 
se peztuefz0 st eqeq “Asatz seqXq zepz0-ySty ey YITM peTORs ere senTea 
e3hq-etdtyrnu so seqkq eyL *3euTOF 00089 ETOTOJOW UT peo As st eAep TIV 


uopqeztuebz0 e3eC 

“y9x0 ‘TXO 

‘woxo ’°6°e - xo e Aq pepeserd exe sentea TeEwToOepexeg “szequmu TeUTOep TTe eze 
OOT ‘0 ‘EZT eTdurexe xz0z ‘sqthtp zo Butxzys e se 02 perTeyeXT ETS soenTea Teupoeq 


squeqsu0D 


90p'4sIV 


*ueppTqzog ere sreqoeTeYD TorAQUCD “WO Eze 
seceds SutTtez3 34Nq GI SYR UT PeMOTTe ou eze soeveds HbutpeeT 
“(ALX0 ‘OPTT3) u~. WHnozyQ (ozxo ‘eoeds) , , ebuezr eyqQ ut 
sxeqoezreyo IIOsw eTqejutad znoz Fo uoTAZeueQeEoUOD 94 ‘SAT ZE 
*quno. 
ey} UT peqyoeTzez you st e7Mq ped styL “stTya YsTTducoDe 
03 4xeQ eY3 FO puSe oYA OF peppe eq ueD ejkq ped y ‘ueAe oq 
ptnoys edAQ ejep styq ut seqdq Fo requmu TeI03 Sy ~seqkq 
qxeq Aq pemottToy qunos ey7Xq-euo e ‘butzqs eTAkAs-Teoseg 
(pepuejxg edAq eqep [aNWS] Queuu0ztTaAUg oTzeunN eTddy 
pzepuejs) requmu jutod butAeoTy pS. pzepuejs AAAI ITA 08 
* (@AFENTOUT) G6Z7‘L96 ‘HET ’Y 
02 9 worz zequmu Aue sutequop ‘peubtsun satq ze :buolt peubtsun 
‘(eazsnTout) Leo ‘esr’ LPT’Z OF 
879 ‘ESP ’LYT’z- worzy zequmu Aue suteqjuop ‘peubts satq Ze : Huot 
* (@ATSsnTouT) 
GES’S9 02 O WorZ requmu Aue sutequop ‘peubtsun sjtq 9[T :3zr0ys peubtsun 
* (@aTSsNnToUT) 
LOL‘ZE 03 B9L'ZE- wWorzy zequmu Aue sutequop ‘peubts s3tq 9T :g2r0yqs 
*(@atsnTout) ggz O23 O WorF zequmu Aue sutequop ‘peubts sqtq g -:zeyo peubtsun 
* (BATSNTOUT) 
LZT ©2 BZT- worzz Zequmu Aue utequod ued AT ‘*sreqQoOeTeYoO 
IIOsw asn{ ueyQ ozou utequoo ues zeyo y ‘peubts sqtq 8 :zeyo 


:butazqsd 


:pepueqxe 


*“MOTeq PeysTT eze pesn soedkq ejep ous 
queumoop sTyQ UT sezngQoNzAs eBAQep ey eqTIDSep OR pesn eq TITTM ebenbuelT syxTT-D W 


sedky ejeq 


*seotaep Butpzopez Aqttepty ySty pue ‘suotqjeottTdde exremagos punos. ‘squeumzqsut 
punos petdures ‘szeqndmon go Ajzetzea zeHzeT & YRTM OsN TOF pepuequyt st JAI 
otpny ‘szeqnduios teuoszed uo xyoeqheTd zoz punos Hutz0yjs zoz ATutew pepuequt 
st ‘setdues Teaneuow 4TqQ-qyhte seTpuey YOTYM ,’XASB., “S3TW STUoTQODeT_ Aq 
‘,8DF0A peTdwes 3TqQ-g JaI ,XAS8., ST ewroZ eher0As punos G8 AAI Wa. TeyQouW 


*pzepueqs 
StU} eUuTsep pedtey oym szedotTeaep [Te Aq peptacad uoTjzeredood pue squemmioD syQ 
seqetoerdde ATqeezh z0eqnduop etddy -ge6T pue Le6t Sutzanp syquouw ueqy go potred 
e zeao sxedoTeaep oTsnu 43TH pTey shutjeour Terenes FO ATNseT eYyR St AII CTPnW 


“suotqeottdde useemqjeq ejep punos jo Bbuyzeys ey} SReQTTTOeF TTT yreau0D 

03 AqyrTtqe styZ “Queumoop styR ut peuTyep yeuroy eyQ wWorTy pue OF 4TEATOD OF 
eTqe eq PTNoys AT ‘jeuTOF eheTOYs AUSeTETZTP e EsN 03 esSCOYD seop UOT eDTTdde 
ue JI ‘“T[TeM se Aeur0sy eHez0js ejep e se osn of yHnoue STqTXeTF AT PUTS PTNoys 
szeubtsep uotqeottdde ybnoyate ‘jewzoz efueyozequt ue Attrewtad st gal oTpnw 


“sqaw otuozq0e Tg Aq pedojtesep 

nS8TTZ Zeur0g ehueyorzequy z0z pzepuejxs ,G8 ddI Wain SYR OF SuTOFUOD FAI OFPAW 
“syqpta otdues 

pue seqez otdues so Ajetrea e Ae spunos peTdues TeuueyoTATNM ro TerneuoU 

yo ebez0qs eyy Burmotte ‘eTqtxeTy eqtnb st qemros ey, ~“spunos petdues 
Hutz0jzs xoy pazepueqs e septaozd (gaI OTpny) Jewr0g eTT_Z ehueqorequL OTpny eqL 


STTd Weurog ETT ehueyorequl oTpny :saIW 
‘pur ‘zeqnduop etddy ‘ebezeyjeeq 33eN pue eUTTW eAeqjs Aq peptaord 


(ora etyquds ‘rretddy’oen) setdues 41q ZE-T OTpay 


90p'4sIV 





FORM and Chunk Registry 435 


IFF Specification 


*qeardzequt 

OR ROU SesoOYoS Ay esoyqR weEAS ‘aATTW WHOA OUR UT syUNYD eyQ TTe Adoo ptnoys 
@dIV Waod & setdoo jeyQ weahord y ‘“syunyo TeuotTAado ey ezouby ATeaTQoOeTES 
03 esooyD ued pue syunyo peztnbez eyQ peer of eTqe eq ysnuU gaIWw WHOd 

esn 3ey3 suoT_eotTTdde Ttw ‘“Teuotqdo eze sxunyo zeyR0 TTy ‘ozez ueyQ z6ejeerb 
yqbueT e sey punos petdues ey3 Jt pertnbexr st yuNnYO eyeq punos eyL ‘“pertnbex 
ST yUNYD uoum0D ey, ‘“Teuotqdo pue peztnbez :sxunqo zo sedXkq omy ere eze"UL 


*sqIyo rATeYQ ere se ‘suoTqoDes HuTMoTTOF eyQ ut peqtzosep 
exe gaaIWw WUOd & UTYATM punoz sedXy yunyo TeoOT QuezesstTp eyy Fo syewroz oyL 


sedky yunyo Teo.oT 


*Ktbuypzoope eqep yerdzequt o3 pezedezd eq ‘op spxzepueqs 

SDII etddw ysow se ozez Touueys so peeqjsut eqep 3yybtr roZ omy Teuueyo 

sesn ATTeENSN TAIN ‘WOTQUSAUOD SYA MOTTOF SeOp QT STEeYM UeAT ‘“UoOTQueauoD 
STUUR MOTTOF JOU op aaIw JO suotgqrzod eulog ‘“sTeuueYyo ppo uo eyep AzeT 

pue sTouueyo wend uo eS jep QySTI YATM pezogjs st eAep oezeqs sOII eTddy eyy uo 


*quouubtsse Aoezrzr0D ey st QUeUMdDOP sTYR 

UT pejstT queuubtsse oyQ /qoezzr0oDUT st stun ‘“oO000$ edAQ AzeyTtxne pue gos 
edky eTtz pesn pzepuejs gaI OTpnw eyR FO ze; Tree pue Z°T suotszen~ “O0000$ edAR 
Azey{txne pue gag edAR eTtF YAM ETTS & uy pez0js st gaIw WiOd ‘II eTddy ue uo 


“uoTsue4xe ey TOF 
nJIW’,, OS sOUeU STTS AAI OTPNW 3eYQ pepuEUMIODeET sT QT ‘UOTSUeQxXe oOUTeU STTF 
eB osn 09 Azewojsnd st 37 eTeYUM ’XINN IO SOd-SW se yous weysks Butqezedo ue uo 


‘aaIw Wiod O43 Fo edXzwroz oyQ se owes oyQ ST STUL  GdIWn odkQ OTT YQTM 
STTS & FO ATOF SQep SyQ UT peT0js st JFIV WUOT O43 ‘SAH TO SAW Tepun ysoquToeEW 
eB uo “TTeM se sueqshs oTTzZ etTddy zey3o ut peTFTquepT eq Aeu seTty gal OTPNY 


suotqeottdde zteyR 

03 OFFTOeds uot QEUTOZUT eTAX® TORS O02 ‘QUeUMDOP sTYQ UT TeAeT peuTyep ‘yunyD 
Dtztoedg uotyeotTddy eyA esn wed suotqeottddy ‘suotjeottdde tre Aq peazeserd 
eq qou Aew uofqeuzozut styQ se ‘yTOF SdTNOSEeT S,OTTF AAI OTPNW UT uoTReUTOFUT 
Kue ezojs jou prnoys suojpjeotTdde ysoqutoey “adIw WuOd eA FO edAyuI0sZ ey 

se ewes ey3 ST STUL ~/JaIV, ST OTTF AAI OFPNW Ue Fo odhQ ETT YsoquTOeEW UL 
‘OTTS agdI OTpny we Jo YTOF eRep eyR UT pezojs ST ‘GaIW WHOT OUR ‘YsoquToOeEW e uO 


swzrosFAeTd Tyo pue eTddy uo agiw Jo ebez0js 
* queumoop 


Sty JO Aeputeuez eyA Hbutpeexr ettym Azesseveu se uegqgzo se eTdurexe styQ O27 TSesFeT 
eseetg ‘w xtpueddy ut punoz eq ued OTT adI OTpny ue Fo eTdurexe peTtTejep erou y 


“ddIW WAOT © UTYQTM sxXuNYS TeS°OT FO Huyrepz0 ey uo suOCTRODTAQSeIT OU OTe eTEUL 


STTd III Ofpnw etduts :¢ eznhtg 


| I 
| JaNss, = aIx> | 
|_yunyo e3eq punos | 


yunyD uouop | 


dV, = edApwr0z 
WOE, = AIA 
yunyD JdIw Wiod 


| I 
| | 
! | 
| | 
| | 
| | 
sWNOD, = AIA | 
| | 
| | 
| | 
| | 


90P'AsIV 


“yunys eB 3ed 
punog e pue yUNYD uouMIOD e& ‘SsyUNYD TeEDOT OMA sUTeQUOD YOTYM JZaIW Wuod eTSuts 
Hututequos eTTy e& FO sysTsuoD GI “STTS AAI OtTpnyw etduts e so eTduexe ue st ereY 


“OTTF ddI OTpaw 
ue dn exyew sxunyo TeDoT sqt Yate Buote gaIw WUOU YW “syxUNYS TeDdoT peTTes 
exe syuUNYyo sseuL “WAOT OY UTYATM poeuTequod syuNYS oYA ere pTeTF syunyoO oyL 


* GdIe 

WHOd & PEeTTeRO st ,aaIw, edAzpwroz Jo yunyoO WIOM W “punos petdues 03 uteqied 
WAOT SYR UTYRTM sXUNYD eYR JeYR seqeotpuT styL “,AsIw, skemte st oedAywroz 
‘SeTTZ @dI OTPNY TOG “YUNYO jWIOT, SYR UT S,JeYM soeqTIOsep pTeTF edAzwxzosy SuL 


*[]syunyo pue odAyuwr0z ‘sqzed omg oguT uexyorq useq sey uot Arod ejep eyy 
3ey2 SION “YUNYO ,WUod, B42 FO uot qzod ejep Fo eZTs eYR sUTeQUOD eZTSYO ouL 


*yunyo WYOd & ST STYQ JeYR SOQBeOTPUT STUL “,WUOT, SABEMTE ST GIAO SUL 
{ 


/(] sxunyo xzeyo 
tedXyuzos az 


feztgsyo Suoct 
‘ary ar 
} qonzqs syepedky 


:qeuzoz Butmortjtozs ey Q 

sey WHOd W “NNOM & PETTeO st aaI otpny Aq pesn euo eyQ 4nq ‘syunyo ZeuTequoD 
yo Zequmu e souTsep seTta 2ewrog ohueyoreqQuI roxy pzepuejs Gs Jal Wan 

*yunyS ZTeuTequoo e ut zeyqebo 4 pednozh exe eTTZ AAI OTpNy ue uT syUNYyoO ey 


*queumdop sty3 FO suoT{OeS ZOQeT UT TTeIeP 

UT peqtzosep ere syuNYyS eseyA FO TIY "99e ‘uOTREWIOZUT OTF TOeds-uoTWeOTTdde 
ez0ys ‘szeqjeuwerzed jueumzqsut ASTI ‘szeyzeu euTzep yoTyM syxunyo Teuotqdo 
ZeYyRO TeTeAes ere eTeyL ‘seTdues ofpne Teny_De syR suTeQUOCD YOTYM yunyD 
e3eq punos e st ezey, ‘“eqex eTdues pue yRbueT sqt se yons ‘punos petdues 
ey Butqtzosep sxeqeuezed queqzodwt sutequod yoTym yunyD uowmoD e st ezeUL 
*syunyo yo sedAq juezesstp FO requmu e FO UOT_DSETIOO e& ST ETTF JAI OTpnw uw 


‘9 pxepueqs worzy szezztp sty ‘“ohenbuet extT-D ano ut Aerre pezts-eTqeTzea 
e seqeotput (/[Jeqeaqyo zeyo ’*6°e) uorqeotzytoeds ezts ou yqtm Aexzze ue AeyQ e3ON 


‘e@ZTSYO UT pepntToutT jou st e3iq ped sy, “pues eyQ 3e peppe eq ysnu 93fq 
ped ozez e ‘yAbuetT ut seqkq Fo zequmu ppo ue st ejep ey JI ‘ary Aq poeuturejep 
ST BQep sTyR JO QEuTOZ YL “YuRyoO oyQ ut pezoys eqep syQ suTequood eAegqyo eUuL 


‘eztsyo pue qryo Aq pesn seqkq g eyy epntout jou 
seop 31 “seqkq ut ‘xunyo ey FO uoT|zod eqep eyy JO SeZTsS SYA ST EZTSYO oyL 


‘qryo 5ututuwexe Xq eqep yunyo eyQ AerdzequT of Moy sUTUTEQep 
ues werhord yw ‘xunyo eB go uotyrod ejep oy3 Jo yeEwTOF YQ seqTIOsep qIyS euL 


fyunyo { 


/* e3ep x/ ‘(J eqeaxo xeyo 


/* ezts yunyo »/ Jeztsyo Huot 
/* aI yunyo «/ faye ar 
} qonzQqs yepedsy 


rzeuuew HutMoTTos eyQ ut ebenbuel exTT-D zno BHbutsn pequesezdez eq ued yuUNYD YW 


90p'AIV 





vices 


De 


436 ROM Kernel Reference Manual 


punog TeuueyotarToW z0z sourezy eTdues :g eanbty 
! ! 
qutod oe tdues euo = | | 


| I l | | ' | | 
Izy l_ty | °° * Izgo_l_tye Izy |_ta_| 


N owezy T ewezy O ewezy 
otdues eTdues eTdues 


‘eseo (TeuueyD omg) cezegs eyR OJ g eANHT_ UT pEeReAASNTT}T ST sTYL “STAeTTeae 
JeuueyS yore TOF euyA UT AuUeEUIOU SUES eYR WoTF QUTOd eTdwes e st cwerz eTdues 
yore 3eYQ YONs peAeeTIeQUT Eee TeuUeYS yore worz squtod etdues eTbuts 

‘ourezy eo [dues e peTTeo st squtod etdues peaeeTrequtT Fo jes Y ‘“peAeeTIejUyT 
exe Teuuey yore worz squtod etdures eTbuts ‘spunos [TeuueyoTytTnu rox 


qutoa etdues ata-zt :p eanbtg 
pepped oz0ez 
eze s3tqd & 
peTstasn{ AzeT st qutod etdures 3tq ZT 


‘orez 09 Wes ere sqtq Bbuyutewez eus 

*seqkq omg ut petstasnf aseT pez0js st ‘TITOTOOOOTOT Azeutq ‘3utod eTdues 
atq-zT Ww ‘py eznbtg ut peqezjeniITt st eseo eTduexe uy ‘“peorez sytq bututewez 
2q2 G3TM ‘peTsTasn£ aszeT st eqep jutod etduwes eyQ ‘s3tq aybte zo eTdtatnu 

e jou st jutod erdures e so yapTM eyQ ueymM ‘(AsxtTz e34q QueoTsZtubys ysouw) 
seqiq xnoxy ut pezoqjs eze sjutod etdues eptm 31q-zE OF -Gz pue ‘se 7kq eezyQ UT 
pezojs eze squtod etdures eptm 3tq-pz 03 -LT ‘se3hq oma ut pezojs ere squtod 
etdues eptM 3Tq-9T 03 -6 ‘e34q eUO UT pezojs exe squtod eTdures eptm atq-qybte 
02 -eu9 ‘se qkq snondtju0D zo zequmu jTerbequy ue ut pez0js eze squtod eTdures 


*yunyD woumop eq 3 ut eztsetdues Xq peutTurejep se ‘eptTM s{tq ZE OF T WoTF oq 
Kew yotys ontea queuetduos-s,z ‘TeeuTT © se pezojs st juytod etdues yoeq “owt y 
ut qutod ueath e Ae punos e jo oeTdues e BSutquesezdez entTea e st jutod etdues y 


‘seuwezz oeTdues pue squtod etdures jo 
sydeouo> omQ eyQ punoze seATOASZT sSeTTS JAI OTPHY BHbuTAezdzequt so zed ebzerT wv 


sewezz eTduesg pue squtog etdues 


* dgI¥ 
WuOd & ut zeedde Aeu yunyD e3eq punog euo Fo umuUTxeU y ‘oreZ st yUNYD woumMIoD 
eY3 UT PTeTs seuezzetduesgumu ey ssetun peztnbex st yunyYD eyed punos eUL 


‘uoTqQoes 4xeu eY4Q UT TTEIEP 

uy peutetdxe eze seuezy otdures pue squtfod eTdueg “yunyD uoumop eyy UT PTETT 
sewezgeTdwesumu eq3 Aq peuturejep st ejeqpunos eyyA ut seuezy eTdues yo zequmu 
euL ‘“punos eyQ dn exeu jeqQ sowezy eTdues eYQ sUTeQUOD PTETF eQeCpunos oeyL 


*mMOTeq UOTQDeS 

eqeq punos BbutubtTy-yoorg eyQ UT ST eZTSYOOTG uo uoTAewIOsUT eT “OTeZ OF 
27 368 PTNoys pue eztsyooTq esn 3,u0mM suoTqeoTTdde qsou ‘jeszyo yATM sw °02 
poubtTe st ejep punos eyQ syooTq eqy Jo seqkq ut ezts ey suTeqUOD AI“ eIep 
punos BbutubsTe-yxootq zoz ReszZO YRTM UCT ROUNLUOCD UT pesN ST EZTSYOOT euL 


“moTeq uotqoes eqeq punos SutuhbtTy-xOoTE 

O42 UT peutetdxe st jeszyo oxez-uou B ACF OSH ‘“OTEZ OF AT WES PTNoYsS 
pue ZeszyzO esn 3,U0mM suOCTReDTTdde As0oq ‘seqkq ut st AeszzO EYL “syATeQS 
eqeqpunos ey Q ut ewerzz oTdues 4srTF SY STEYM seUTUTEREp PTETF AeszFFO OL 


90p"4sIV 


*eztsyo pue arya Aq pesn seqkq g ey epntouT you seop Ary ‘seqMq ut ‘yuNYO 
ayy FO uoTazod eRjeEp eyR FO EZTS SYR ST EZTSYS eyYL “,GNSS, sAemTe st GIy ouL 


‘yunyoeqeqpunos { 
7(] eayeqpunos zeyo peubtsun 
feztsyootq Sbuort peubtsun 
/qeszzo Huot peubtsun 


faztsyo Huot 
/aryo ar 
} qonzqs zepedxsa 


punog 20J dIy> ¥/ ,ANSS, are yeqpunos outsepH 


‘sourexzy oTdures Tenqoe eyQ suTequoD yUNYD eqeq punos euUL 


yunyS e3eq punos 


‘aarIw waoa Azeao ut perztnbez st yunyD uowumog ‘euo ATuo pue ‘euo 


*puoves zed seuezy eTdures ut yoreq 
peketd eq 03 st punos ayy YOTYM We e7eT STdues CYA ST PTETF Se ReYeTduUes oYL 


‘uoTqQDes yxeU 
ey UT peqyIOsep eq TITM qutod eTdues e Jo QeuIOy eYL “ZE OF T worTZ TequmuU 
Aue eq ues AI 4‘ Autod etdures yore ut s3tq FO zequmu eYQ sT ezTSseTdues eyL 


*s[Teuueqoumu seutq seurezgzoTdwesumu 

ST SETTF SYR ut squtod etdures zo zequmu Te}0R eY_ “YXUNYD eQeq punosg eyQ 

ut squtodetdures so zequmu ey3 zou seqjMq so zequmu ey se ewes ey A ATTresseDeU 
qou st sty, ‘seuwezz etdues so zequmu eyQ suTequoD pTeTz seurezgzeTduesumu oy, 


“OTAET TEAR 
Jeuueyo yore oz owty UT QuoewoU owes oY4R wory AUTOd eTdues e st oureazz oTdues 
yore AeYR YONs peaweTeQUT ere TouUeYD yoee wory sjutod eTdures eTbuts 


*ATAzZ0Ys peqTzosep eq TTTM YoTYM 
‘yunyD e3eq punos ey3 ‘xUNYS zSe|YQOoUe UT pezogjs eze seTdures punos Tenzoe eUL 


*‘euezyz eTdures © peTTeo st squtod eTdues peaeeTrequT Fo Wes W 

“peaeeTreqUyT eze Teuueyo yore worz squtod etdues eTbuts ‘spunos Teuueyorqtnu 
zog ‘pequesezdez eq Aeu steuueyo otpne Jo zequmu Auy ‘o je ‘punos 

Jeuueys aznoyz suvow y pue ‘oezejs sueeu Zz ‘punos oTucydouou sueeu [T JO enTeA 
‘punos eyy Oxy s[TeuUeyD oOTpne Jo zequmu eYy sUTeQUOD pPTeTF sTeuueyoumU SYL 


“gt sAemre st eztsyo ‘xXuUNYD woumoD eyQ TO" 
‘eztsyo pue gry Aq pesn seqiq g ey epntouT jou seop 3r ‘seqhq ut ‘yuNYo 
ey3 FO uoTaZod eAep eYyA FO SZTS SYA ST EZTSYO CYL “,WWOD, sXemTe st QIAO SUL 


dyunyououmop { 
Jeqeyo tdues pepuse3xe 
/eztsetdues qzoys 
/sowez go Tduesunu S5uot peubtsun 
/sTeuueqounu qaoys 


feztsyo 5uot 

‘aryxo ar 
} qonzqs syepedAéQ 

/* xUNnYD uouMIOD TOF CIAO »/ .JWNOD, awoumo5 eutzep# 
‘punos petdues ey3 Jo szejeuezed [eQuewepuny seqTzosep YyuNYD uoumloD eUL 


yaunyD uoumop eu, 


90p'ssIV 





FORM and Chunk Registry 437 


IFF Specification 


fyunygozexzeEW { 
‘() szexyzen xexzreEN 
/sxeyxxze_oMU qzoys peubtsun 


feztsyo Suot 
fazryx> ar 
} qonz3s yepedxy 
arIzexzeK 


/* AANYD TOYTeEW TOF AIA «/ VMIWW, outszopH 


“MOTOq UMOYS ST YUNYD TSYTEW © UTYATA e3ep eYQ TOF WewrToOZ oy, 


qeuzog yuNYD zexz7eW 


*zoQeUTUIEQ [Inu eyQ TOF peuturexe oq HuyzAs eyQ uF TEeQDeeYoD 

qoee 3eyqQ eztnbex shuyzaqs DO ‘“rSE\OeTeYO AsITy EY JO sserppe ey OF AUNOD 
Bbutzas ey Sutppe Aq Bbutzqe e zeao dyys weo wexhord e ‘shutzysd buysn *sxunyo 
ySnozyy buyuueos ueym zeao peddyys ATQuetoTZJe ezou ere AeyA esneoseq shutsz3sd 
sesn gal otpny ‘sbutzqs eTAqs-Teoseg so peeqsuy (zejoereyo Huy Weuymxe A [TN e 
Aq pemottos se3fq 4x03) shutz4s-D e shuyz3s er0Rs SETTI G8 TAI Wan Sulog :e370N 


* yzeu 
ey3 Fo eueu ey Bututequop buyzys yxe  eTAys-Teosed & ST PTETF SUeNTEYTeEU oy, 


suotqysog reyxTeW ewexry eTdues :g ernhtaz 
g uopatsod 0 woTatsod 


y. v 


Vv ee eT 
| | | | 


| | | | | | I | | 
| | | I | | | I | | I | | 


ZT wotatsod 


sewezz eTdues 


*squtod etdues zou seqiq 

jou ‘seuwezy otdures exe uopatsod zozx sqtun eyQ 3eY43 SION “T oT ATSod Qe st 
e3ep punos ey A ut euezz eTdures puocces pue AsItz ETA WEEMREG STTEJ WeYR TEexTeEW 
e eTTym ‘ozez uofyAtsod 3e st eAep punos syQ uy suerzZ eTdues yAsITZ SYA eTOFEq 
STTeF eq AoyTEu wy ‘“sewexzzy oTdues omy ueemgqeq TTes AtTenqdeouod sreyrEW 
“pTetz uotqtsod ey 3 Aq peutwzejep st ejeEp punos eyQ ut uoTATSOd s,xexXTeEU SYL 


“py ours eyQ sey ZaIW WOT ures oY UTYITA 
xzexzeU reYQOo ou se Huot se ‘zehbequy ozez-uou eatTatTsod Aue eq wed pt eUL 
‘aaIW WAOT & UTFAQTM JeyTEU AeYQ sets QuepT ATonbyun yey requmu e st PT SUL 


fzeyzew { 

/eurenreyxzeu Sutzqsd 
fuofpatsod Suot peubtsun 
‘PT arIzexIeEWn 

} QonzQ5 zyoepedxQ 


‘PITOATER qzoys yepedxy 
*qeuxroz HbuyMoTTOFS eyA sey rexreEU ¥ 
szeyreW 
*squtod pue pue butuutbeq 
doot yxreu of szeyxZEM sosn ‘O8A{ON STYR UT zZ9QVeT peuTyep ‘yYunyD Aueumzysul 
eqYL ‘seztsep uotjeottdde ue sesodznd z9eaeqjeyM TOF pesn eq ued sTEXTEW 
“eQep punos oy uz suoTqtsod oj 3utod AeyQ sreyrTeEW suTeQUOD yUnYD TSeXTeEW SUL 


yunyD reyxTeW SUL 


90p'sdIV 


*-Ktbuypzoooe yesszszo pue eztsyootq eyepdn prnoys At ‘XOoTq pezts AuezesZsZTp e OF 
eqep punos ubtTeex oj speeu uoTQecTTdde ue ZI ‘“or9eZ 02 AESzZZO pue EZTSYXoTq 
9y3 30S pINoys At ‘queuubtTe eazeserd jou seop uotqeottdde ue zr ‘“pextnbexz 
Rou st sty ydnoyate ‘eqjep punos ey4Q Jo quewubtTe eateserd oj Ax3 prnoys eTTs 
ddI otpny Bbuyastxe ue Aztpow qeyQ suctyect{tddy ‘ezts y,ooTq eAetzdoxzdde eyQ og 
@zTSYOoT AOS pTNoys eyep punos peubTTe-yYooTq eAtazm yeyQ suoctjeot{ddy ‘seTtz 
ddI oTpny Butqeez> ueym orez 03 YeszZo pue EZTSYOOTG eyA Aes pTnoys queuubtTe 
YSDoTQ ynoqe eres Q,u0op AeYQ suoTAZeOTTddy ‘peubtTe-yD0Tq eq 03 peeu jou 

seOp BRep punos eYyA AeYQ sEeQeOTpUT OFEeZ JO EZTSYOOTQ W ‘e Aep punos ey ubtTe 
Ptnom nok yotym 03 YOoTq eyR Fo seqkq ut ezts eyQ setTztoeds eztSsyoorTq euL 


*TTem se Azepunoq yoTq e uo pue o3 seqkq eQeqpunos ey 3 

ButMoTtTe ‘sewezz eTdues pttea puokeq pueqxe ueo seqkq ejeqpunos eyQ 3eYQ ‘009 
SION “eRQeGpunos syA Fo seqkq AoeszzZo AsAxTzZ CYR Butddtys Aq peysttduoooe st 
STUL ‘“N YOOTQ Fo Hhutuutbeq eyA Ae sqzeqs ewerzy eTdures Qsxtz eyQ ‘z, erNnbtg ur 


eqeq punos peubtiy-y0Ta =. eaznbta 


Z+N AOOTA I4+N ADOTG N D0Tq I-N _400Tq 
t 
|<- seqkq ->| 


| | | eztsyootq | 


<-_sowezjy opdues sowezsetTduesumu -><-- jeszzo --> 

! | | 

I\\ pesnun \\I souezy eTdues I\\ pesnun \\I 
"L exznbtg ut umoys se ‘yuUNYD eQeq puNos ey 
yO sxejeuezed eztsxooTq pue yeszyzo SYR YATM peystTduoooe oq ued QuewuhtTe stTyL 
“SYDOTQ EeZTsS-pexTsZ YIM eQep punos petdues ubtTe 03 YsTM ‘otpne Fo yoeqKeTd 
pue Bbutpzooez swt Teer eansue of ‘ReYQ suOTQeOTTdde ouos oq Aeu ereyL 





eqeq punog SutubtTy-x°0Ta 


-se3kq 

ped ou qt zeyAebo 3 peyoed exe souezy eTdues eyQ ‘osTMeXTI ‘“weyQ uweeMqeq 
seqkq pesnun ou eze ezey 3 /zey,0e60 3 pexoed exe euwezz oTdues e utyqTM squtod 
etdues ey, ‘owt 3 Sutseexzout Jo repzo ut AtsnonbyAuod perzoyjs ere souwezy eTdues 


punog TouueyotT3zTNW TOF suotTQueAUOCD ourery eTdues :9 eznbty 


| 
zeque. | 
aybtz 


—_— 


Joeuueyo 9 
zeAUeD 


punozszns 
yeuueyo yp 
qubtz 


zeer 


JTeuueyo ¢ 
zeque. 


oere ys 


| | 
| I 
| I 
| I 
| | 
| | 
| I 
| aset | 
| | 
I I 
| | 
I | 
I | 
| | 
I I 


I | 
| I 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
I | 
| | 
I | 


ayhtz 


€ 
JTeuueyo 


‘9 ernbta ut suotqueauod eyQ MOTTOZ ptTnoys nok ‘spunos Teuueyotqtnw 
zog ‘jutod etdures eTbuts e st ouwezy otdues e ‘punos ofTuoydouow 10g 


9290p 'AsIV 





vices 


De 


438 ROM Kernel Reference Manual 


“spTeTs eztsyo eyq Aq st szepeexz oTAgs-gar opreueb ut yzrede 

syunyo omg eqQ TTEQ Of Aem poob yw ‘“yunYyD Quewumazaqsul Jal 
oTpny ey3 se oures OY} JOU St YOTUM ,,LSNI. JO GI YatM yuNGS 
e seuTyep osTe euro, queumazyjsul peTdues soIr eTddy euyt 






*3990ON AISY 






‘aaIw Waod & uy azeedde 
*qTeuofqdo st yunyD Aueumzysul eUL 






ues yuUNYD AueUMAqsUr eNO UeYQ STON ON 






“peseejTex st queumzqsut ue uo Aex © z98eQze sINDDO 
Artensn eseyd eseetez ey, “punos e yorq SutAetd so eseyd eseeTer eyy UT ST 
quoumzjsut ue ueym podetd eq 03 st 3eYq3 dooT e setytoeds prety dooyeseeter eq, 








‘punos e Sututeqens st 
queumzjsut ue ueym peXetd eq 09 st e439 dooT e setztoeds prety dooquteqsns suL 






*qutod oe tdures yore 

JO OENTeA eYQ eATEY sueeU qp9- eTTYUM ‘QuTod eTdues yore Fo enTeA SYA SeTqnop 
sueew qpg ‘ebueyo ou sueeu qpo ‘eTdwexe z0z7 ‘sTeqtToep eze sqtuq ‘“peketd 

ST AT weyM punos eyA Fo uTeh ey efueyo o3 yotym Aq qunowe eyq3 st uteb eqs 






- (Aqyootea qseyqbty) ~zt wSnozqa (AapootTea ysemoT) T ‘senTea Aqyootea IdIW eze 
83TUQ ‘eatsntout ‘Aqtootea ySty pue mot ueemyeq st AQTOoTeA uo-ej0u EY FT 
peketd eq prnoys e3ep punos ey, “e3ep punos ey3 so yoeqheTd rox seTQyoOoTeA 

go efuexz peqsehhbns eq3 Asfoeds sptets AatooteaySty pue AyyOoTeAMOT eUL 








*seNnTeaA ej0U IGIN eze 
eIONGSty pue eAONMOT TOF sQtug ‘oehuex styQ UTYATA eq OF EAEY JOU sSeOp ejOU 
eseq eyy ‘“eaTsntToutT ‘ySTY pue MOT SYR UEEeMReq oj0U © AeTd 03 peqsenbez st 
queunz3sut ey gt peAetd eq prTnoys eqep punos ey, ‘“e3ep punos eyA Jo yoeqheTd 
xox pzeoqhey e uo ebuexz peqsebhhbns ey3 Azyoeds spretz ejonySty pue SJONMOT SUL 











‘pestez eq prTnoys Ay 3eYQ UeeU srequmuU eATATSOd ETTYM ‘poeTeMOT eq pTNoYsS 
punos ey3 Jo youTd ey3 3eYR UWeew szequmu eaTReHeEN “0G+ 03 OS- wory ehuez pue 

(euogTuUes © FO OOT/T) s3QUeD UT ETE sATUN ‘“yXOeq peAeTd st QF UEeYM punos ey 
JO youtd eyQ reATe pTnoys Aueumzysut ey Yqonu Moy seuTUTeJep PTSETS eunQep sy, 









“09 ST D STPPTN “L2T 
qSnozy3 9 ebuez ey ut eze pue ‘szequmu ejou (eDezzeqUT TeITStq Juewumzysul 
Teotsnn xoz wAuozoe ue st IGIW) IGIN E2e satun ‘oT _eoTFZTpom youtd qnoyzye 
eqep punos eyQ yoreq sXetTd quoumzjsut eq} YOTYM Ae SjoU eYQ ST SAONESEeq CUL 





‘oz sXemte st eztsyo ‘yUNYD Aueumazysur eyR FOZ ‘“seqhq ut ‘yUnYD 
ey3 FO uoTAZ0d eAeEp eYR JO EZTS EY ST OZTSYO “,LSNI, sheaTe st GIA Sys 





syunyoyueumzysul { 






{dooyeseeTex doory 
‘dooyuteqsns doot 
suteb qazous 
{Kapoorteaqhty xeyo 
LXQFOOTCAMOT zeyo 
Jeqonqhtq zeyo 
JOQONMOT zeyo 
feunqep zeyo 





Jeqoneseq zeyo 





Jeztsyo Huot 
/aryzo ar 
} qonzqs zepedx3 








ar3ueumz3sur eutTzep# 





/* AWYD syuewumzAsul OF GIASx/ ,LSNI, 


“MOTeq peqTzosep st YUNYD QuewumrAsuI ue uTYATM eQep SeyR Fo euros ouL 





Zeureog YuUNYD Wueumazgsul Sul 





90P'4sIV 





‘eoetd seyeq HButdoot ou pue yabuet eat qebeu xo oxzez sey 
queufes dooT ayy ueyq ‘eseo syQ Jou st sTyR JI “woTyTsod pue ey ueyQ sseT 
eq ysnu uotytTsod utheq eys ‘“doot e so uotytsod pus sy syxeuw dooypue eq, 


*queuhes doot ey3 so uotqtsod utbeq eyA syzeu AeYR pT rexXTeEU e st doorqutbheq oyL 
*yoeqketd Bbutanp pezouby exe squtod doot eyy ueyq ‘petytoeds st butdooton Jr 


zZ S5utzdooypremyoegpremiz0g eutyep# 
Tt butdooypzemiz0yg eutyop# 
0 Butdooyon eutsep# 


tpeuzoszed eq 03 st Butdoot zo edkQ yotym setztoeds epopketd cyt 


*peqdnzzequy TTWun 
utebe zeao pue zeao pejzeedez st uzeq3ed dots-dt1tz styL ‘“uotyysod utbeq eyA oF 
uot3tsod pue eqy worsy spzemyoeq pedeTd ueqq pue ‘uot yTsod pue eyq 03 uOTWTSOd 
utbeq eyq worz peketd ysatz st queubes doo, eyQ ‘SutdooT premyoeq/pzemz0sy YITM 


butdooy ouwexzz etdueg :¢ eznbta 


uot tsod pue uotatsod utheq 


ee 


| | I | | I I | I I | I | 

|__|__|__I<-=-= guewBes door --->|___|__|__| sowezz otdwes 
* queumz4sut 
Buttduwes e uo Aex e FO SseETeZ EY se YONsS ‘UoTROe zesn e Aq peyqdnzzequy 
ttaun Atpeyeedez peketd st ‘queubes doot eyA peTtTes ‘suotyfsod pues pue upbeq 
ayy uweEemjeq queubes ey, ‘“uoTyTsod ufbeq ey ye utTebe sqreqs yoeqketd qutod 
YOTYM Re ‘uoTATsod pus eyy 073 senuTQUOD pue uot yTsod utheq ey qsed senutquoD 
‘punos ey 3 zo butuutbeq ey ye sutbeq yoeqhetd ‘butdoot pzemzoz Fo esed CYR UI 
“butdoot pzemyoeq/pzemiog pue Bbutdoot premzoz ‘doot e AetTd 03 sem omy ore 
ezey, ‘“uwotytsod pue ue pue uoptytsod utheq e ‘squtod omy yATM peyzeu st doot ¥ 


tdooy { 
‘dooypue przrexreEW 
idooyutbeq prz8exzEW 
fepoyketa  az0qs 

} qonzqs zepedksy 


*dool © seqTzosep mMoTeq emngQoONzAs eYL “punos eYyR ueyybueT oj repz0 
ut peqeedexz eq of punos ey3 so uoTAzIod e HutmoTTe ‘pedootT eq ued ejep punos 


Butdoot 


‘eqep punos eq Aetd 03 esn prnoo ‘etdues 
e@ se yons ‘Queumzqsut ue 3eyQ szejeurerzed ofTseq seUTzZep YUnYO Queumszysul ouL 


yUnYD queumzAsul syL 


“adIW WiOd 
e ut zeedde ues yunyD zexTeEW EUO UeYA eTOW ON ‘“TeUOTIdO st YyUNYD TexIeEW SOUL 


‘xeuuew zeTnotTqzed Aue uy pezepzo eq jou peeu szexzeU ey, “wey uSeEeMjeq 
se3Xiq pesnun ou y3T zey e6o0q peyoed eze szeyzew ‘snyy “were eq sAemTe TTTM 
zeyzeu Aue so yRbueT eyq ‘seqXq Jo zequmu uese ue ore TEYTeEW e UF SPTSTF TTS 

esneseg ‘“seaTesueyy srexzeu ey Aq peMoOTTOF st AT ‘ozez-uoU st sreXTe_UMU 
JI" yUNYD TeyxTeW SYA UT sTeXTeEW JO Tequmu eYyW sft PTSETF sroYTepUMU SYL 


‘eztsyo pue ary Aq pesn seqdq g ey epnTouT jou seop AIT ‘seqAq ut yuNYS 
eyy FO ucTyZOd eyep eyR JO EZTS SYR ST SZTSYO eu, ~ MIWW, SkemTe st AI¥O ouL 


90Pp"AsIV 





FORM and Chunk Registry 439 


IFF Specification 


*zeyxTEU e& OF AUTT & pue AueumoD eyy rox dureqs-outQ e& 
eze XeyZ “yunyo Gs AAI WH. OY UT puNozZ Jou sernqeey omQ sey YUNYD sQueumt0D 
eq 3nq ‘squeumop rox pesn eq ueD AeYR (JZISY UT pesn) yUNYD uoTReqouuy ue sey 

»$8 ddI Wa. “ddI WaOd SY UF sQueuMIOD ez0RS OF pesn ST YuUNYD squewmiloD euL 


yunyD squeumtop euL 


‘aaTw Waoad etbuts e ut astxe Aew syunyo otTzypoeds 
uotqeottddy yo zequmu Auy ‘Teuotado st yunyD oTstToeds uot ject Tddy euL 


suopqeotidde ey3 03 oTstToeds ejep eyQ st PTETF e3ep SUL 


*qzoddng jteotuyoez otddy yata pezeqstTbez se 
erzngeubts zreqoezrey aANOZ SYA OF 3E8 eq PTHOYS PTETF styA ‘YsoquypoeW yy 10g 
+, sopd, 03 jes eq prnoys ptetz edéajso eq3 ‘II eTddy ey3 zog ‘our ‘zeqnduop 

etddy worzy suxoz3eTd uo unz yotym suotqeotrtdde Aq pesn st pretz edAzso euL 


‘eznqjeubts zeqoezeyo azanoz s,uoTqeotTTdde ey eq TTT styq ‘suotqeot Tdde 
ysoquutoen rog ‘“uopqeottdde zetnoTqzed e seTsytquept eznqeubtsuotjeotitdde eyr 


“eztsyo pue aqryo Aq pesn seqkq g eyy epntTouT jou seop Ar “seqhq ut ‘yuNnYyo 
ey3 FO uoTazod eAep ey FO EZTS SYR ST EZTSYO CYL “,Tddv, skemtTe st GIy ous 


fyunyoots oedsuotqeottTddy { 
?[T]ezep zeyo 
Jeznqeubtsuotzyeottdde edXiso 


feztsyxo S5uot 
tary ar 
} qonzqs zepedsy 
/* ‘yunyo ofztoeds «/ 


/« worqeoytTddy zoz aIy> x/ ;Tdav, arotsfoedsuorjeottddy eutzepE 


‘pqe ‘uopaqtsod zosazn> AseT ‘sTeaeT uoTQeoTsTubeuw 

se yous szejewezed e3e4s r0OR}Tpe ez0js OF YUNYS sTYyR esn oF Quem qqhtuU spunos 
S3ATpe 3eY3 UCTRIeOTTdde ue ‘oTdwexe zoqg ‘“szoyqne uot ReoT Tdde pue sxredoTeaep 
Kq zeaveosjeym sesodand Aue xox pesn eq ued yunYD oTZTOeds uoTAeEOTTddy ouL 


yunyo oFsToeds uotqeotTddy eqs 


*aaIw Waod & ut zreedde Aeu 
yunya buppxrovey otpny euo ueyQ ezouw on ‘“TeuotTAdo st yuNnYyD Hbutprooey otpny eYyL 


90p'4sIV 


*stseydue Hbutpropez eqtTzosep 

yotym ‘9 eq4q Fo pF pue ‘Eg ‘Z SATq eq PTNOM AsereQUT TeEZeUed JO ‘“eoUeTUeAUOD 
xoy yunyS Hbutpzopey otpny ey3 ut peqeottTdnp st uotjewzOsUT sTYyYL “seoTAep 

oTpne weemjeq otpne Te3yThtp Fo uotsstusuez, ‘,e3eq OTpny TeIThtq pequeserdey 
KyzeeutyT roy yewrog uotsstusuezy, TetTzes - Huyzeeutbug otpny Teathtq zoz eotTQoer 
pepuemmosey sav, ey} ut peTstoeds exe eqeqsnqzeqsTeuueyoosay Jo seqkq pz ouL 


‘yz sXemte st eztsyo ‘xunyD butpzovey otpny eyy tog seqAq ut ‘xXUNYD 
ayy Jo uotazod eAep ey3 JO eZTS ENR ST EZTSYS SUL “,GSaw, sAeaTe st ary ouL 


Jyxunyqobutpzopeyotpny { 
JCyz]eqeasnqeqstTeuueyosay zeyo poubtsun 


Jeztsyo Huot 
ary ar 
} qonzqs zepedéQ 
/* “yung +/ 


/= Sutpzoovey otpnyw r0F GIy x/ SUTFOpF 


,asaw, arSutpzoseyotpny 


* seDTaep 
Butpzocez oTpne oj jueutqred uotyeurosut sutequo> yunyD butprooey otpny eyL 


yunYyD Hutprosey otpny euL 


“squeumzysut ey} JO TTR xOF yuNyD eyeq IGIW Bbtq euo ueyR Queumzysut 

xed yunyd e3eq IGIW eUuO esn OF 7ERR9eq ST AT ‘AAIW WHOU & UT peo js eq 

04 exe squeumzysuT TexreAes Toyz sebessou eatsntoxg weqsks IGIW JI “ddIW Waod ®& 
ut qstxe Aew syunyo e3eq IGIW JO zequmu Auy “Teuot3ydo st yunYyD ejed IGIN SUL 


“eqep IGIW JO weerqs e suFejQUOD PTETF S3edIGIN PUL 


*eztsyo pue arya Aq pesn seqkq g eyy EpnNtToUT you seop 3I 
*seqkq ut ‘yunyo eyR Fo uoTAz0d ejep eyR Fo ezTSYD “,IGIW, skemTe st GIyxo euL 


fyunyoeqeqdIaIn { 
‘([J]eqepramn zeyo peubftsun 
feztsyo Huot 
‘qIyo ar 

} qonzQqs zepedk4 

auTsepH 


/» 4unYD e3ed IGIW TOF GINS x/ -ICIN, are edidiIn 


“yung 

B3eq IGIN SYR UT pezojs eq ued obessow eatsntToxg we sds IGIW STUL ‘“SuTYyoeu 
mou ey TOZ ehessou satsntoxg weysks IGIW eYR UT pequeserdex eq ATSATT TTT 
sdooT eseyL “yunyD Quewumzgsurl ey A uT peutyep sdooT omy eyQ ueyR erow sary 
Kew jueumzqjsuy buttdues meu e ‘atduexe zoqg “yunyD Quewumzysul eyQ UT pepnTouT 
jou eze 3eyQ szejeuezed Auew utequoo Aeu squeumzjsut eseyy roxy sebessou 
eatsntoxg weysks IGIN SY, “woT_eoTspoeds ggI OTpny ey} UT pepnToUT ue09eq 

qou eaey 3eYQ szeqeuezed ovey ATOXTT TITM AoyQ ‘QeyTEuU oj SsuUIOd squeUMIySUT 
ero SY “TTOM Se YOOTq ayy UT peT0ys oq UBD eQep IGIW JO seddy reyRo yHnoyqTe 
‘sebessou eatsntoxg weysks IGIW ex03s 03 st yUNYD styA Jo esodand Azewyad cous 


“IGIN UO Ss{TeIEp eTOU Toy ‘uOT_eTOOSSY IGIW TeuoTAeureqQuI 
ey wors eTqeTTeae ‘O°T uopTqeotTstToeds eoezzequI Teqarhtq yueumzysul 
TeotsnW OF TSeFET eseeTd “e3eP IGIN ET0Rs OF pesn eq UBD ZUNYD e3eq IGIW SUL 


munyd e3ed IGIN SUL 


“02% 
eq reaeu ued ‘suoseez TeANQONAAS TOF ‘pTeSetzF eEzTSsyZo s,AunyO 
queumayjsur 3eur0g 3ueunzysur petdues sori etddy oyQ seereym 
‘oz sSARMTE ST PTETF SZTSYO s,YUNYD Quewumszysul GI OTPNW SUL 


90p4sIV 





vices 


: De 


440 ROM Kernel Reference Manual 


“gaTW WaOd & UTYATM 3stxe Aew yungo owen euo ueyQ exou oN *TeUoTQdo ST 
yunyo euwex eyL ‘“punos petdues ey 3 JO eweu ey suTeQUOD Axe EYL “ZUNYD eueN 


IMOTeq peqyzosep se ‘yunYyo eyQ wo puedep 4xe 3 Jo sQueqUOCD 
euz ‘eztsxo Aq peutuzeqjep st 4x09 UT szeRQDeTeYD Fo requmu ey, ‘Sutz3s 
> & zo Butzqed e jou st Ay “szreqQDeTeYS TIOsy eaznd sutequoo pets 7xe 3 SUL 


“9x03 ©G3 eseo sty UT ‘yUNYD eYyR Fo UOTZIOd eAep eYQ Jo eZTs SYR ST EZTSYO OuL 


“stseqquezed esotT> eyQ zeqze (07x0) eoeds 

e st ezeyRZ pue eseoremoT st ,o, ENR ‘HUNGD yybTrzXdop eyR z0og *ATeATQDedsez 
‘yunYyD uoTQejouuy zo ‘yuNYD ayhyzhdop ‘yunYD zoYAnY ‘XUNYD eUWeN eB st YUNYo 
ey3 zeqQeqa uo butpuedep ,ONNW, ZO ’, (2), ‘,HLOW, ‘,AAYN, ZEqRTS SF AIA SUL 


syanyo3xen { 
+[] 9x03 zeyo 
feztsyo Suot 
‘aryo ar 

} qonzqs yzepedsQ 


90P"4sIV 


euTzepFR 
eutzepH 
eutsep# 
eutzep# 


/x yunYD vuoFqzejouuy r0oF qIyo /ONNW, Cleuen 
/= xunYD aybtzAdop z0z Ary , (?), aTewen 
/* UNYD ToyAnw FoF AIA sHELAW, areuwen 

/* yUnGD ewen FoF AIA sTAYN, CIeuen 


*Teuotqdo st syunyo eseyq 3 
go yoeg “4xeQq go ATeTos sqstsuoD uotTqiod ejzep zyteyR ‘syunyo 4xeQ STE TTIW 
"@TTS 1uS8 daI wa. Azreae Fo uoTAtuTsep eyQ UT pepnToUT ere syunYyoO anoy SseyL 


uoTqejouuy ‘qybtxkdop ‘zoyqny ‘euen ‘syunyD 3xeL eUqL 


“adIW WaOd OTHuts e ut 
zeedde Aew yunyD squeumop euo ueyQ ezouw oN ‘“TeuoTQdo sft yUNYD sQueuMI0D SUL 


*yunyD squeumtop eq 

Uy squeum0D ueemjeq butpped ou sft ezeyQ os ‘yQHueT ut seqAq Fo szequmu 

ueae sXempe ore squemiod ‘“seatTesueyy sjueumioo ey3 Aq pemoTTOF st sTuL 
“yung squeumog eyQ UT squeMMOD Jo TequmU ey sUTeQUOD PTSTF sQueumooumuU eq], 


‘eztsyo pue aryo Aq pesn seqiq g ey3 epntoutT jou seop 3r “seqhq ut ‘yuUNYD SYR 
JO uoptyzzod ejep eyA Jo ezts eYQ ST SZTSYO eqL *,LWOD, sXemjTe st GIy SUL 


/yunyos quewumog { 
‘[(] squeumo. queum0p 
Jsqueumooumu  3z0ys peubtsun 


feztsyo Huot 
/aryxo ar 

} qonzqs zepedk3 

ar jueum0D 


/x %ANYD sjueumOD oF GIAO */ ,LWOD, eutszopH 


qeuzog; yUNYD squeum0D 


*adIw waod eTbuts e 
uy aeedde Aew yunyd squeumop suo ueyQ SrOUI ON *Teuotgdo sft yunyD squewmm0D SUL 


“FTSOSAT WUouMIOD eYy SsUTeQUOD PTOTF 3x03 CUL 


“buyzasd © YATM SETQETTeAe eq PTNom ueyR squeumoD rebuoT qonu buymoTTe *Kayquenb 
ATQ-9T © ST STYL “QuoumoD eyQ dn seyeu 3eqR 3xeq SYR Jo qabueT EY ST FUNOD eUL 


‘zeyxeM e OF PEXUTT Jou sft QueumoD styR eq But QeoTpUT 

‘ozez st TeXTeEU ‘OsTMIENRO “TEexTeEU WeYR FO CGI SYR SF PTET 7exTEU YQ UEeqR 
‘zeyzew e 03 Guyrzeser sf JueuMoD eyA JI “ZuUeMMOD e se sreyTeU Jo suoTIdTzDsep 
Buoy ex0js 03 suoT ject Tdde smoTTe styL ‘“TexYTeuU e OF peXUTT eq ued QueuMIOD Y¥ 


“post ‘t Axenuec eouts spuooes Fo requmu eYyQ 
eze sqqun ‘qsoquToeEW ey3 UO ‘“sLET ‘T Azenuec eouts spucdes Jo TequMuU eYyR ere 
sqtun ‘ebtuy ey uo “peqzeezD sem QueumoD oY} UEYM seqeDTpuT duwejseuTZ euUL 


fqueumop { 
iqx0Q zeyo 
fqunoo  3z0ys peubtsun 
{xeyxzeu arreyzeEn 
‘dureqseut3 46 uot peubtsun 
} qeonzqs zopedsy 


"qx0eQ 
Aq pemotTogz junos 3xe3 e pue ‘pt zeyrew ‘dureqs owt} e& JO systTsuoD JueUMIOD Y¥ 


queum0D 


90P"4sIV 





FORM and Chunk Registry 441 


IFF Specification 


S3IW OTUOTADeTT ‘,e0F0A peTdures 34q-8 AdI ,XASBin 

S8QIW OTUCTROETA ‘,SeTTa Jeuzog ebueyorequr roF pxrepuejs $8 HAI Wain 
“uoFqetoossy IGIN TevoTzeuzrequr 

eu ‘.0°T uoT_eoTzZToOeds ‘eoezzequr TeqThbtq queumzqsul Teotsaw -IGIW. 
S9TOT AN ‘XTOX MON ‘QeezRS pUzP yeeq 09 ‘AQeTOoS buyreeutbug otpny 
+, e3eq otpny TeatSta pequesezdey AtxeeutT rox QewrO, uotsstusuery 
Tetzes--butzeeutbug ofpny Teathtq rox eotq_OeIg pepueumoDey sav, 
vdaw ‘.€°Ta qewzog eTta ebueyore ur otpny, 

‘our ‘xeqnduop etddy ‘,,jeur0g queumzysul petdues 

soIr etddy ‘zooo$ eddy Axetttxny ‘gag edAz etta :e30N odAZ OTTa. 
‘our ‘zeqnduop etddy ‘uot3ytpg puoses ‘, Tenuey sotzeumy etddy,, 

‘pur ‘zeqnduop etddy ‘rr eumfoa ‘,, ysoqutToeW eptsur,, 


eouereyey reyRANT 


ddIw Waod eTdueg :TT erznbta 


ewerzy eTdues 4200788 euezy eTdues ysI1TF 


I~ zmelpryt)* * * |_Zy ll f£ y_} e3eqpunos 
| _| ®ZFSyxD0Tq 
| | qeszz0 yungo 
! eZTSxO eqeq 
| ar4> punos __ 
dooypue ‘dooyesee Ter 
dooqutbeq‘ dooyeseetTez 
eponketd: dooyeseater 
doorpus * dooquteqsns 
dooyutbeq* dooquteqsens 
epopketd: dooquteqsns 
utes 
Aqtoortenysty 
KATOOTAaAMOT 
e7onydTYy 
SQONMOT 
eunqep 
ejoneseq 
ezTS4yo yunyo 
arx> quoumz3sulL 
Io Neds toe lost stele ol P al eurenroxzew 
uotatsod 
PT 
ourenzexzeuU 
uotatsod 
pt 
szexzTe_UMU 
ezTSyo xunyo 
ary ZOYIEW 
eqeyetdues 
eztsetdues 
sourez jo Tduresumu 
sToeuueyoumu 
eztsyxo yunyo 
arx2 wounloD 
edAyur0s 
eztsyxo 
aryx> 


JIIV WIOL 


90PpssIV 


‘syz0J edTNOsSeZ eTpuUeY ued AeYQ suSQsAS OTTF YsoqRUTOeEW FO yTOF 
eAep eyy UT pezojs st JAIW WHOA OUL ‘“AdIY WAOd ETSuts e Huyutequod eTTz e 
etTduts st STTF AGI OTPNY UW “aaIW WUOd & FO eTduwexe ue sejerqsn{TT IT ernbta 


-Kk[butpzoove 
pe zepdn eze syxunyo eouepesezd zeySty eyy 3eYy3 erNs eYEU OR syUNYSD eDdUepeserd 
ZOMOT SYR OFUT BRep EATAM AeYQ suotyeottdde zo Aqatrttqtsuodsexz eyy st 3I 


“yuny e83eq IGIN ey UT puNozZ squtod doot ButTyAoTTFZUOD reAO eoDUepederd eyYeQ 
yunyD quewumzysul eyQ ut squtod doot ey 3eYQR sees euo ‘eTdurexe roxy ‘Ayorezety 
yunys eqy ye Butyoot Aq ‘sxunyD zeqQ0 YATM sqQOoTTZUOD UT sesoyT sXemTe yuNYD 
DTzZtoeds uotjeottddy ey, ‘“yunys zey3o Aue ut uotqeuzozsut Butjortguos xzeao 


eouepeverd sexe sXemte yuNYD uoumIOD SYA UT UOTREUWTOFUT “AseMOT EYQ sey yUNYD 


DtzZToeds uotjeoTTddy ey3 eTTYyM ‘eouepesead yseySty eyQ sey yunYD uoumIoD eYyL 
eousepesezg yunyd :oT eznbtga 


eouUspece%rg 7seMOT yuny otztoedg uotqeottddy 
yunyd esd IdqIn 
yunyo Besse otpny 
yunyo ieeacinahe 
yunyo aiprsiieo 
yunyo asa 
cranny eee 
yunyo Seis 
yunyo Pree 
yunyo neta 
yunyo aus punos 
souepeverg yseyhtH yunyo acca 
"OL ernhtgz UT peqAeTAsnTIt st eouepecsezd sty, *“syunyo 
XOJ eouepecerd e bututzep Aq peatTosez ere sqAoTTZUOD yong ~punos eyQ doot 


03 pesoddns uotqeottdde ue st moH ~QuezesZTp ere squtod dooTt eseyy gt sueddey 


aeym ‘“squtod doot eutgzep oste Aeu yunyd e3eq ICGIW SYR UT BQep eaTSsNToOXY 
we jsks IdIW pue squtod doot soutyzep yunyD Queumazysur ey ‘eTdurexe r04 
*uoTqeumosuT e3eottdnp utequoo Aew aaIw WYOd TOF syuNYO TeooT syW Fo TeTeASS 


eouepevezg yunyo 


“daIw WAOdT © UTYRTM AsSTxXO 

Keu syunyo uotqejouuy Auew ‘Teuotado st yunyD uoTAeQouUY ey, ‘“peeqsuT pesn 
eq PTnoys yUNYD squeuMmIoD Tnzyzemod ezoU eYL ‘“AAIW WUOU & UTYATM pebexrnoostp 
ST YUNYO sTyA FO esH ‘QueuMIOD e suTeQUOD 4xeQ eYL_ “YuNYD uotTWzeQouuy 


‘aaIW WHOd & UTYITA Astxe Aew yunyo yybtzAdop euo ueyy 

ezow on “Teuotado st yunyo 3ybtzAdop ey, ,, our ‘ebyuy-ez0poumiod Té66T (2) n 
sueew , “our ‘ebtuy-ezopoumiog T66T,, 3X03 EY HuTuTequos yunyo qybtszAdop e 
‘etTduexe zoqg ‘“zeqoexeyo qyhStzXdoo ey se seazes , (9), GI XUNnYo eYL “rTeUuMO 
aybtzAkdop ayQ Fo oweu ey Aq pemoT[os e Rep e& suTeQUOD pTeTF 3x83 eYL “punos 
ayy TOF eoT Jou yyhbtxrAdoo e sutequoo yunyD qybtzAdop ey, ‘“yunyD ayStzAdoD 


*“gGdIW WAOT & UTYATM AstTxe Aeu yunyD ToyAny euo ueyQ exzou 


ON ‘“TeUoTAdo st yUNYD zoyQnY ey, ‘punos poeTdures e Jo ToOReSTD SYA ST oseD 
STYR UT TOYQNe uy ‘“seUWeU TOYANe eZOU TO eUO sUTeQUOD 4xeQj eYL “YxuNnYD Toyyny 


90P'AdIV 





vices 


: De 


442 ROM Kernel Reference Manual 


uyosog SxTH 
‘syueuL 


SAIY CTUCTROeT_ FoF eseD woy pue uyosog extW Aq ceptp~exnted 


sezemaqzos Butqxroddns 


subesemezg { 

/» eouenbes Buykzyoeds ,z,°°,e, Jo Suyz3s x/ ‘[ogleouenbes gqixqn 

/* YoFzeupue eqy Fo Toyaeyeq AztTpou sjtq x/ isBetx SLIGaiom 

/x* 80TIJFTC UF souerZ weemjeq SuUyy TEUTUON +/ 73P ONOT 

/+ eouenbes ey3 Ut sowery JO TeEqUMN +/ /seurexyumu CuoM 
} qonz3s zopedky 
/* proper ASTd »/ 
/x (Q'e°°'K'z/K-*'q’e etoks ‘eouenbes ezoubl x/ Z000X0 OudJOL_NOSA SUTJOEPH 
Jn °° 'q'e'2/K-*'q’e eToks ‘eouenbes ezoubrI x/ TOOOXO AIOAD NOSA CUTFOPH 
/» s6eTa x/ 


(N71 / 104° s84' 14.) CIOMEN NOSd OUTIOPH 
spedg xyunyqo 
eouenbes yorqkeTd euezz 043 setztoeds yunyo NOSA SOUL 


tuofqdtzoseq yunyo 


00P’WENV 


eucUu 
tpxooez y3ASTd 
(OW. 8s / ON, W.) AISXeW WaNy euTzep# 


:pedg yunyo 


dewjtq pezeuytue ue se STTF STYZ sesfFqUepT YuNYoO WENY SUL 


uofadtzoseq yunYyo 


eweszz Suyuyeuer yoee z0Z AGOM PUES WATI WHOA * 
euwrezy 38273 O43 xaog** 
SMOTTOF OWeITy QSITTZ Wall WuOd** 
SZXOTOD uoumMOD seuTzep deuzojToo awio""* 
yjdep pue ezts uoumop seutyep xzepeey deujtq aquWa’”” 
MOTTOS setqzedoird Wall dowd’ 
setqzedozd ezeys 03 swAa'II 5utmoTTOF sMmOTTe LSIT WAIL LSIT" 
uoyjzemzoszuyt eouenbes yoeqKetd NOsa° 
dewjtq peqzeuyue ue se OTT STYR SETS TIUEPT WaNny 


*peeqsut 

pesn eq ueo eouenbes Azexrqtqze ue ‘jes st syTq eseyy Fo rSeYRTeU 

3I ‘seouenbes ofuyqtrobte omy Aztoeds OUdOL NOSA Pue AIOAD NOSA 

‘uoyqeurue eaetyoe 09 sdewytq Tenptatput ey3 Jo eouenbes 
yoeqKketd ey3 setytoods (NOsa) yYUNYoO souenbes ourezz oyL 


“SITs eyQ ut reedde 

Key3 zepzo ey3 ut ,°°" 2 q e, ‘zeqDerTeYS e Aq peTeqet st 

pue ouexy & peTTeo st setzes eyQ ut dewytq yoeqg ‘“yadep pue ozts 
ewes ey Jo sdeuyjtq so setzes e st (WHNW) deurjtq peqeuyTue uy 


“NOSa@ PUe WANY :peuTzyep ere srepeey yuNYS meu OM] 

‘quTegexnteq worz setts se peaes sdeuytq ueezDs TTNZ 

ebzeT exe sexznqotd pue quyegexnteq wory seysniq se peaes ATTensn 

sdew3tq ,TTeus, eze sqoefqgo ‘“punozbyoeq ey3 ut erngqoTd e YQTM 
punozbezogz ey ut eAou pue rzeedde sq0efqo cept, exnted Ur 

“oeptAeXNTed UT esn r0Oz sdeurytq peqeutue eTduys euTyep OL :asodund 


‘QT YQTM 3OTTZUOD ATQueQreapeUT 30U 
TTTM sqeumroz TeyRO 3eYR Os QEMTOS sTYR YsTIGnd TTTM noA edoy I 


‘zetndod ezou eureseq ebtuy eq} se ebzeure prnom yeurozy [TnzreMmod 

ezow e 3eq3 edoy ey3 W3TM ‘oeptad Aq esn xox AemTozZ eQeaTad & 

eq 03 pepuequT sem 4I «“3eMZ0Z UOTQeEWUTUe esodind [ezeueH e eq 03 

peubtsep jou sem QI ‘TTe sn 03 efuer3zs pue meu Area sem prepueqs 
GdI SYR weym euyQ e Qe Agzpot Tduts zoz peubtsep sem Aeuxoz SUL 

(zoyqne ey wory ejoOu) 

(cepta exnted ‘zeweza Aq pesn wiroz dew3tq pejzeutue) WENN WIC -AILIL 


(COPTA ExnTeq ‘xrewezqz) wrozy deuytq peqeutuy 


90P’WENV 





IFF Specification: FORM and Chunk Registry 443 


“uofFqQeztTezeueb etTqeuoseex 

& SXTT sues yotym ‘Gg poyyjeu Fo Axequoos eyy ut uoTqeredo yO eATSNTOXT 
SYR SREOTPUT OF PTETF s3tq eyz Fo Z ATq Hutsn we T “py poyjeu uoTsserduoD 
wate ATuo yatm osn rox (“DUI ‘WiuYds FO weyuog Azep ‘Qewxr0z WINY OUR 

yO zoZeeTD TeuThTr0 eyy Aq ) pepuequt ATTenQoOe sem PTET .SITq, C42 :3LON 


‘9 03 308 st ostTe Buty ykzeae -- 


/*x MX SutQeotput «/ ‘py = S3tq° zpHuTue 

fo = eutqsqe’ zpyutue 

!] = owt yTez*zpHutue 

Jy x0q*  AoFd* qouq*zq“utuyans = yY*apquUTue 

im? xoq* jo td" qouq*rgutuyin> = M*azpyutue 

/T = eaeeTIEQUT’ IpHUTUe 

/» Sutpoous gat x/ ‘Gg = uoTqexedo*azpyUtue 


:qes I ‘seysnag wtuy 205 


‘zpHutuy { 
‘[ot]ped azxgoa 
888 Se 
sQeszzyO OFUT Huot sjeszzo OFuUT ArOYUS 
TeOT{AIEA Tequoztz0y 
(pepooue yabueT unz) ony OTa ou 
souetd [Te TOF suetTd yore r0z 
OF OFUT euo ogut eqezedes 
R- (0). 4 ero 4s 
eqep Bbuot eqep jy20ys 
T= o= #3Tq 
rsqtq go Buyueow y/ ‘/s3Tq ONOTN 
/» pesn jou x/ ‘oped aLxan 
/*« 27 03 SaTnHezZep O y/ ‘/eaPeTITERQUT ALAN 
feutaTez ONOTA 
seuTysqe ONOM 
!K‘x QaoM 
a‘ qaomn 
/x*8T B3ep ereym yseu oueTd :ATuo WATI WOx x/ iyseu aLAGo 
/* 
(epou uotssezduioo sureyez5 of2q) yL= 
(3342) B3TSd TeoTqzeA 83Aq G= 
‘epou eqteq Sbuot/y_zoys eztTTezeueD P= 
epour eqTeq 3T0YS E= 
‘epou eqyteg Bue q z= 
‘epoul WATI YOx T= 
Atq>eztp 3es oO= x/ ‘uotzezedo aixan 
} Qqonzqs zepedk3 


:3eurosy YuNYS CHNW S43 St eTeH --- 


*,,sourezgu,, st We 
AOOT I [Te quesezd jy ‘jueudoteaep BbButznp Azessoeoeu sem requmu uoTszeEA SUL 


‘yunyoutuyvdd { 

/* POsT ION x/ ‘sBbeTz SNOT 

/x UOT AeuUTUe SYA UT seurezz Jo zequmu ,/ /seuezyu Gyomn 
/* Y=sUOTSIOA QUeTAINS »/ iUOTtsSrIeA GCYOMN 
} qonzqs zepedky 


ryunyo Nwdd ey3 Jo QEUI0Z eYQ ST eZeH --- 


JOP’ YSNIG WINV 


eqep epow eqAtep 
repeey uoTyeutue 
N ovwezy 


eqep spou eyTep 
zepesey uoTyeutue 
py ouery Wall Waod 
ezep spou eyTSp NWLIG ~ 
zepesy uoTjeutue CHNY ° 
€ ourezz WTI Waod 


eqep spou eqTep Wi1d ~ 
Zepesy uotqeutue CHNY ~ 
Z owezy WaTI Waod 


xAGOoG 
SNWO 
“yunyD eT39TT umo Au Nwad 
SNaD 
SNuD 
SNYD 
SNYO 
SONU 
SND 
awa 
saaq 
ano 
aHWE * 
ewezy SITy WHTI Wi0d 
WINW Wuod 


‘WETI TeTATUT eyq ut zeedde AtTengjoe syunyO AeyM UT YOTIeTIeA eReTETOR 
oq ySnous eTqtxeTy eq esrNoOD FO pTnoys Aepecsy AAI SUL “vYsnzg wtuy, ue 
se® III 3utegqd Aq andqno wrog aaI SY FO SANQONIAS SYA FO SUTTANO Ue ST STEER 


“zeaemoy ‘petstiTduts eq ptTnoys seysnzg wtuy peer o3 

szepeez uwtuy Bbutystxe Bbutkstpow zo qof ey, ‘“AemAue soysnzg wtuy peer TTT 
swezbozd Butqstxe ou os ‘20 eaTSNTOXY ueyq reyQer uotyerzedo ez0jg eB esn YOTYM 
pue (Zz ‘e°T) 9 FO SARSTTEQUT Ue sAeY YOTyM s,wtuy, g edXy3 Aetd AtTuo TTT! 
ptzom ebtuy ey3 ut szeAetd utuy Bbuyqastxe ey TTe ‘ebpetmouy Au oj ‘zeaemoH 


‘Ketd eTqeszeaez MOTTE O73 IO SATSNTOXT 

esn seatep ey ‘ostw ‘butddttz-ebed ezempzey ysez so esodand eyQ ros 
wojsno WINW Tensn e434 st yotym ‘qzede Zz seurezz usemjeq ueyy reyqer ‘sewer 
queocefpe ueemjeq peqnduios oze seqtep Hbutueeu ‘{T Fo eAeeTIEQUT Ue sAeY seqTEp 
euL ° (ddIIY S,3Uey WTC uo peseq) BHbutpooue eqrep pequetir0-e7kq ‘TeoTATEA e& 

St yotym ‘Hhutpooue ,g¢ eddq, & osn seysnig wtuy * (weyuog Azepy Aq ‘oedg wtuy 
JAI OYA oes ‘QeWTOF WINW SYR FO ucTAdTZOSep e zoz) AboToutwzey WINY 2s5Nn OL 
‘euo snotaezd e& pue ewezy e ueEeMjZeq eDUEeTEeTZTP pepooue syA Jo pestaduoo 
yuNYO WLId & pue yuNYS Zepesy uoTjeEUTUe GHNY Ue suTeQUOD YyoTYM Fo yore (s,NATI 
A[Teez 4,ueze YOTYM) §,WATI, Juenbesqns Jo zequmu Aue pue ‘uot ewtue eyq so 
ewery 3SITZ SYR ST YOTYM WHIT TETITUT ue Fo systsuod wrog WINW ue ‘ATTeOTSseg 
‘qewroy ,WINV., ddI 943 UT YSTP uo peaes ore III qutTedd Jo ,seysnzg wtuy, ey, 


S4IW OTUOCTQDeT_ ‘eATTS ued 
‘qutead go zoygne ey Aq uotadtzosep e wor 
qewio0og aaI ysnig wtuy qutedq 


yeuzey ysniq WINY 


IOP 'USMOWINV 





vices 


: De 


444 ROM Kernel Reference Manual 


*ypeq 

sewexzy OMA WOIFZ SsEDUSTEeTZTP SE pEeTORS Ore seUeTy TEYRO TTS 3Nq 
‘[ owezz wozy seoueTesZTP se pero As st Z ewery WeYR SION “UO 
os pue ‘peXertdstp st 37 pue yw weeros TEeRTe OF pesn ere ¢ oCUeITZ 
ZojJ seouezezsTp eyR vey, ‘pedkeTdstp st 3t pue q USeezOS TeqTe 
03 pesn eze Z ewerzy TOF soODdUETETZTP CYR USeyL “uSeezDs eYQ UO 
peodketdstp st w euezy uey, “a O3UT 3T eQeoTTdnp pue yw ojUy eueIZ 
TeT3ITUT eyQ peoT 03 st epow yoeqKeTd Teurou ey, ~“reYR0 SYR 

03 euo worzz Aetdstp eyA youtms ATqueqsut o9 Aqtttqe eyq pue 

‘gq pue Ww peTTeo ‘sueezos oma sey euo esoddns ‘styQ pueqszepun 
ZeQQ0eq OF ‘“pesn st Bbutzezznq-eTqnop ueyM resjnq users 

ueppty ey ut Bbuyuyeuwexz ouwezy CYR St AeUR se YOeq sourerz 

OM ST ourexy ,snotaerd, oyq ‘ATTewroN ‘ourexzy snotaezd e wors 
seouezesstp xzteyq Atuo BHButastrt Aq peqtzosep uey A eze sewers 
quenbesqns ‘erznjotd gar ‘pepooue-yqbuet-unz ‘Teurou e se 

ewezy [eTATUT eyQ quesead of st swINw Jo Aydosottyd Tezeueh eyL 


MOFATOAO ZEeUTOT WINW T°T 


*quey utc Aq pedojteaep Butpooue e3hq 

pepooue yRybueT unz TeoT37EA eYQ ST epoD Mou UT pedeTd buteq ATQuezinod 
euo Atuo eyA se ysezequT TeofTzogsty Fo ATAOTAASs ere eseyA Fo AsoW 
*qeur0s WINWY ©U3 UT peonpoz{UT ueeq eARY soUTEYyos UuCTsseiduoD [TerE8eAeS 


‘eanqoyd gal TItas 

[eurou e se owexz TeTQTUT eyQ AeTtdstp of eTQe eq OR pue sqewrToF JAI 
Sutastxe yqtm AqrrttqTyeduoo umuytxeu upTequteu oj pextsep seM AI 

- (suyatzobte uotsseiduoo-ep quetotsse yhnozy3) euty yoeqKeTd pue 
(uofssezduos yhnozy3) xsTp uo eoseds ebexzojs Sey YO ezTWTUTYU Oo7 pue 
sewezz FO seouenbes ‘yoeq AeTd pue ‘ezoqs of eTqe eq OF SEM QUeQUT 
euz ‘zeqndwoo ebtuy ey uo sesuenbes oepta peqeutue zo uotjzonpord 
ey xoz ATTeufHtr0 eqzedg ye pedoteaep sem euros AAI WINY SUL 


WOFAONPOTAUI O°T 


ZL66-Z6E (ETZ 

SOP06 FTTED ‘eotuoW eQques 
"PATH OOFd STTZ 

‘op queudoTeseq stbey 

hq 


weyuog Kze5 + 3o0eRQU0D 
T9TS-B89L (PTL) 
€9926 STTPD ‘STITH eunbeT 
BROTIED ET OP THOEZ 
“oul YLuvds 

:Xq pezedeid 


se6et AeM p -eRep UOTSTASY 


suoy zeuruy Tao Tog Qeurog JiI uy 
WINY 


wroz uofAeutue Te 


90P'WINV 


*pedg wyuw euy FO €°Z°Z UOT_IDeS UT peqTzosep st g edXky xox Hbutpooue eyL 
‘pedg utuy ey3 FO Z°Z'Z UOTIDeS UT peqTzosep se st sXUNYS WILT FO Fewrog ouL 


*9uo Fo peeqsut mozr zed seqkq Jo zequmu ey  ppe 
nok uotjeutTzsep eyQ ut e37Mq Axed eyQ OF 406 03 os ‘ATTeQUOZTIOY 
ueyq zeyqez ATTeotyzzea pessoerduoo st ejep eyR WeYR puTW uT reEeg 


“uoFVeuTysep eyq 
oqut at But,wox ‘seutq , juno, zeedez og entTea e37hq e Aq 
pemoTTos ‘e7Aq qunoo e Xkq pemoTTos e7Mq 0 & St STYR - NOU 


*KXdoo 03 seqkq 

aya Aq pemoTTos st 31 “ATROETTP YOX OF eQeEp Jo seqkq 

gO zequmu eYyQA FO AuNOD e st AepuTEever syA pue FFo pexseu 
ST ATG TY CUL “30S ATQ TY eYZ UATM 94hq e st stu - aWnd 


*‘ozez-uou st ar “dtys 
03 eT ‘premzoz zequTod ,4sep,, ey eacu oq smoz Aueu moy 
skes 3eyQ TeeTO 3Tq TY eyQ YITM eA4q e st STYQ - GINS “T 


*puTy YOorYUM uo 

Sbutpuedep eqep Fo qunoue ButAzea e Aq pemMoTTOF pue ‘spuyy eezqy 
yo eze sdo ey, ‘ouwezzy QseT OYA wWoTFZ UUMTOD sTYyQ uT eHueyo ou 

$s ,ezeyA sueeu qsnf 4t ‘xO s,3eYR ‘ozeZ st QuUNOD-do eyA FI *sdo 
gO zequmu e Aq pemoTTos qunoo-do ue yaTAM sqzeqs wuMTOD yoeg 


“yoee soqiq 

oz JO suUMTOD pf SAEY PTNom sueTdatq OZXLT & eoUeAsUT TOF Os 
‘eptm seqkq Jo zequmu ueae ue sfemtTe ore seoueTdatq eyQ ‘Tezeueh 
url ‘ypee seqiq 00z FO suuMTOD OF eAeY PTNoMm eueTd3tq 007xXOZE 
w ‘Ateqezedes pessexzduop st oueTdatq eyQ Fo uumToo-ejiq yoreg 


*“stseq 
euetd-Aq-euetd e uo pewzozzed st uotssezduosep/uctssezduop 


(‘uoTQeQueumD0p gaId 5, 3uUey UTL Fo 
Butpzomez s ,weyuog Azep uo peseq st poy jeu ey Jo uotadtzosep ButmMoTTos eyL) 


“¥9 TO O TEYRTS ST 

qeszzo euetd ysatz eyA sny_ ‘euetd 3eyQ ut ebueyo ou sem ereyQ FF ‘Or0Z IO 
‘euetd Bbhutpuodsezzos eyA z0F eRep SYA OF AXunYo wuTd ey Fo Huyuutbheq eyQ woszs 
(seqXq ut) qeszso eyQ zeYATe eze sjeszzo euetTd esoy, *(Asouw 2e) 9 4sIzTF SUR 
sesn ATuo qutedd yOTYM Jo ‘sqezzo euetd ONOT OT UITM suTheq yuNYo WITd oUL 


‘eurezy 4sITF EY yORq shutzq snyy eATed ASeT 9y2 

butktddy ‘ojo ‘euezy prztyQ eyQ seqezeued ewexzz puopes eyy 02 B4TEd PUoDeS 
ey Butktdde ‘euezz puoves eyR seqjezeueh oweszy TeTAITUF SYA OF BATEd AsSATT 
eqa butktddy * (syuny> WiTd pue GHNY ButuTequoD SWATI ®°T) s,eaTed OT Aq 
POEMOTTOF OweTZ TETATUT ue Eq TITM STEYR ‘sewery OT YIFM Ysnrg wWTuy ue TO" 


JOp"'ysMq'WINV 





FORM and Chunk Registry 445 


IFF Specification 


‘uyewop oTTqnd oj epod uotssezduosep pue uotssexzduo> yR0oq peseeTex 
sey ey ‘xeqqang ‘shut4taM s,wtrl worzy uexyeQA st QueuMoOp styQ UT 
poyzeu styy Fo uoTAdyzosep eyL ~“AeUTOZ WINW SY UeYR JueZETZTP 

SF YOTYM QeuroZ OTTF AU STY UT peZTTTIAn st pue quey ute Aq 
pestaep sem poyjeu ey, ‘“sebeut peztatbtp se yous eqep Astou Azea 
oz weve uotsserduos quesep Hbutonpozd ye [ngsseDdons Azea st ynq 

‘szezzo p poyjeu qeyQ suotqdo Auew ey resJo jou seop poyjeu sTyL 






uofsseizduop Teotqzen, e7kg G°Z°T 


“MOTeEq Z°Z'Z UOTADES UT PEUTeQUOD ere poyjeU sty wo sTTeAeqd 






“seuTyoeu jsour ut etpeu efezojs pe ytUt{T o3 enp eTqezeseid 
ST (XZ seurfjeuos) uotssezdwop ze430eq eyQ ‘remoTs ATTeOTZTIIER 
Buteq jou peeds xyoeqKetd ‘seseo qsou ur ‘sebeut peztarhtp se 

qons eqep Astou Azea rz0z ATTetoedse - [Tem se ssexdwoo jou seop 
qnq (epou eqTep pepooue—yadueT-unz-Teotyrea-eqAq eB soUeSSse UT ST 
yotym) epou q3sTF ey ueyQ Feqsezy yoeq AeTd epow styy ut segrtep 
pepooue-yabueyt-unz-TeoTygzea-Azoys eyQ eoTQoerd uy ‘“quey utr Aq 
pedojteaep sem ‘moTeq ‘epou uastzy eyQ ‘peztTrTeutz Bbuteq sem sty 
eutTy eYyQ 4noqy ‘oj0 ‘(yxoeqkeTd eszeaezx sqtwxzed yoTyM) epouw wox 
‘uofssezduod TeqUOZTIOY TO TeoTATeEA TeYATe ‘uoTssexduioD prom 
Huot pue Aroys yI0q z0z eptaorzd suctjdo ‘eureyos uoTssexzduol 
e3TSp yno-yqyHnoyq3-TTem e eptaczd 03 Adureqjye ue sem epow stTyL 

-zeyqe6oq and ATTQsey ezeM sepou uoTsserduoD eQTep OMA aeacge eyL 






epou e3Ted TezeueS 7° Z°T 






*ebtuy oqinL 0z089 3TG-zeE e& uo pesn ueymM peoeds yoeqketd eyQ 
5uzaordut ut ysezequt zo ATuyeu st epow eqteq buoy eys, 
"yunYyo WLId ZeTTeus e UT syrTNsez epow styQ ‘seoue QsUT 
qsour ur ‘spzom-buoT Jo peejsut peaes ere spr0mM-ji0ys 
aey3 ydeoxe spou eqteq Buoqt eyy 03 TROTQUEPT st epow sTYyL 






apow eATeq 3T0US E°Z'°T 








"yoeq seurezz omQ yQTM ‘pzom-buoT Aq pzom-HbuoTt ‘eurexzy mou 
eYq3 serzeduod suo se eqep ey HutTyQetnoTeos pue ‘/eqep eyQ pToYy oF7 
zezznq e Butaey Fo sqstsuoo Attensn yunyo eqep sty BHutqonzyAsuop 






“9uo yoee TOF peaes oq 03 BAPY AOU Op sAeszJO Os Tey AeboQ 
unz eq ues ebueyd yotyM Mor e& UT spzom-HuoT eroUW IO Z 

zo shutz3g ‘ouetd ueath e ut eoetd exeQq sebueyo ou ZT 
peaes Buteq ejep ou yqtm ‘Ajteqezedes petpuey st ouertd yorg 
“MOTEeq Z UOT_DSS UT pessNostp pue uMOYS st AeuUIOZ QOexXO 
ey~ ‘dew3zyq eyQ ut JeszzZo YQ YQTM HBuoTe ‘quezeszTp 

ere YOTYM sprom-Huot ouwexzyz MOU TeN_oe eYR serT0RS EpoU sTYL 






epow eqqeq buot z°2°T 


‘aeBewt eyq BbButqonzysuosez uodn yox e43 
Hhutwuzozzed ut peumsuod oultQZ 9yQ UT ST Spou sTyR FO eTOeASWO 
zofeu yw ‘“Sutpooue-yybuet-unz Bbutsn peaes st dewytq mou 

sTYyR UseyL “UeTezzZTp ere AoyQ eTeyM BATq T pue ‘TeOTQUSPT 
B@IOM SsOWeTZ OMQ SYR TeAeTEYM S4TqC O YQTM deuy7tq Mou e UT 
S3INsez stuL “yoOeq souwezrzy OMQ pUe oUeTZ MoU ay Jo saqiq 
Butpuodsezz0p TTe ueemj_eq (YOX) IZO-eATSNTOxe ue suzozied 
Atduts euq ‘“etduts eqtnb st epou yox FO uoTRZeeID sUL 
*zoftzedns zez ere sepou eATep eyQ ‘Tezeueh url ~4sezeqUT 
TeoTroAsty TOF erTey pepntout st pue Teuyhtxzo eyQ st spou sTYyL 






epow Hox T°2°T 





‘oeds styq ut pepntout ATquezznS uotssezduoD Jo spoyjeu 
ey3 FO YoORee Fo outTyAno Tezeueb e oath sydexbezed HutmopTToy eyL 









90P WINV 





“eINQONITAS ETTF WINW SY UTYQTM seuTQNOZ UoTssezduoDep 

/woytssezdwod sty pezTTT yn eM eZeH “WINW UeYR AuUeTeEZFJTIp st YoTYA 
qewroy STTF AAU S,WTC YRTM STYQ esNzUOD QouU oq “Auey UTC Aq peubtsep 
se Butpooue yybuetT unz TeotTArea e3hq eYQ ST poyyZeU YyAsTF SUL ~“peeds 
yoeqketd zo/pue ezts eTtTF FO uoTAeztwtydo eyA xoOyF xesn SYA O73 eDTOYS 

eB szesZO STUL “QeUTOF UOX ST AT VOU XO TeYQeYM pue ‘TeoTATA IO 
Tequozfz0y st uotssezduod sy eyAeym Hbutpntout suotydo Tezenass sey 
YyoOTYM eueyos uotssezduos pxzom Huot ro 3z0ys Tereueb e st poyjeu yyrNosZ 
eYL ‘“spoyqeu sezy3 3saztz eyQ Jo Aue Jo swInw Sutqezeueh Aonpoazd 
TetToremos e FO uMOUX soUeQsuT ATUO eYA ST STUL “0°'Z WO g poy qeU of 
Peyoqtms anq ‘O°T woTszreA UT poyjeu pxTYZ SYR SEZTTTIN dE edeosooptyp 
stBew qonporzd eyZ ‘“3sezequt Teotzoysty zoz ATutewu eze sexy 4sAzTtFZ SUL 
*peutzep ATquezaznod spoyjeu uotssexrduod ewexzjy-oj-owery eaATF STS OTSUL 


* (SUOTQETNOTeDS epou 

eatTep eyQ °6°9) suotqeTnoTeEo uotssezduoo eyA butwrogzed zoz sowexzy 
omy snotaezd ay zo ,Az0gsty, & XOF STOW omy pue ‘ouwerz QxOU eyQ 
JO uotqeez> zoz euo - sdeuytq eezyq ertnbez [TT WINY ue proODeI oO 


SWINY B5utproDea Z°T 


-sn yqtm Aeqs 02 eaey TTtM yotym Aoueqstsuoout 

ue Atqeqozd st styR ‘ezoszezey, “Aewrozy styR peAetd/peqezeueh 

YPOTYM SSESTST OQ BSOTO IO peses[er XeYATe syqonpord TetozeumI0D Jo 
zequmu e& ereM eTSeYR TTQUN pejou jou sem ADueAstsuocouT styA ‘TeAeMOR 
*sewezy osoyqy roxy eR3etxrdoaddeut st wroy WATI ey JO osn eYQ snyq 
‘suotqequeseirdez deuqtq peateTreqUT jou ee syZUNYO WLTIG ey ZeUR SION 


*szezgznq yR0oq 03 pettdde eq jsnu ehueyo oyQA ueyQ ‘auezy e YRTM sandD0 
a¥WO © JT 3e43 WINY ue BbutkeTd useym ered eye, “uoTAeuTUe syQ 
ybnozyq ehueyo jou TTT (WHH °5°e) epow Aetdstp eyy pue ‘deuytq 
2yQ FO SZTS SYA AeYQ ST SWINW UT uoTQdumsse otTseq y ‘eq ReTed 
ZTOTOOD sy TeATe Of syxUNYD GYWD eq PTNoM etduwexs pooh y ° (ueyy 
@ZTTTAN Of suezborzd zeXketd ut peoetd st epod se pue) Aressaoeu 
peusep se ssay3 Jo yore ut peoetd oq Aeu syunyo rzeyA0 ‘uotTAtTppe 
ul ‘eTsY oq TITM yUNnYD xGoOG & ueYyQ ‘pesn st epou uotsse2zduoo 
UoX Tpto esyA JI “sepou uopsserduod eqrep eyy TOF ejep syQ 
suUTe_QUOD YyUNYO WLId eYL ‘“owezz uotjQeutue eyQ o3 Hbututeqired 
szeqeuered [Teuotytppe sey pue CHWa JO suOs sajeotT{Tdnp yotym 
‘GHW © FO peeqsut ‘CHNW Ue UTeQUOD WATI sWuod Auenbesqns euL 


"O= Sq PTRNOYSs pTeTZ uotyerzedo ayy ‘ezey st 4T FI “owexzy 

qsaty ay roz eQep BHButwty eptaoad o3 ezey zeedde ued yunyo 

GHNY ue ‘pertsep JI ~* (aqHWa eu Aq peqeoTpuT se spou uotssezduop 
Tebet zeyR0 Aue oq Aeu 4nq) yunyo eqep pepooue-yybueT-unt 
pzepueqs e oq ATTewrOu TIT AGO PUL “932 ‘ONUD se yons 

‘syunyS WAII Teurou eyZ TTe utequod ued WATI WAOd TeT3tTut euL 


Wid * 
CaHNY * 
€ euezz WaIl Waod 
eBQep epou eQTep WIIG ° 
yunys zepeey uotjzeutue aHNY ~ 
z ouwezy WETI Waod 
xao@ * 
auwo - 
‘euwezz 3st zo BbututyA zoz yunyo 
zepeey uotqeutue Teuotydo GHNW °° 
eqep gar eddy Teurou aHWa - * 
ouezyz 4SITZ WHII Wuod * 
WINY WuOd 
2 (SOTTS 
qeuzogy aarI FO Bbutpueqszepun oTseq e sey Tepeer syQ seumsse 
STYQ) SMOTTOZ se st QeUTOJZ OTseq SAT pUe WAOd AGI Ue ST WINW 


90P'WINV 





Devices 


446 ROM Kernel Reference Manual 


“sepou uofpssezduoo 
eaznqny TOF esn erngnz z0z ped e st sTYL (ot]ped azazan 


sqeszzo osut Huot sqeszyo osuT ArOYS 
TeoTqrEA pequoztzo0y 
(pepoo yqbueT unz) ony OTa ou 
seuetd [Te r0F euetd yore rox 
ASTI OsUT suo ogut eqezedes 
aox 30s 
eqep Buot eqep yzoys 


T= 3058 O= es 
:@eZe esn QuezINdD TOF sAtq xXTs SUL 


‘ozez eze KeyQ eznsse 03 
g pue yp suotqdo ut s3tq peutyepun yOooyo pTnoys 
epoo zeketa *sbhutaqes 3Tq 7 uotado eq3 YQTA 
eTqTAeduIo> eq (epow yox rOF se yons) eznqnz eyy 
ut pesn sbutaqes 3tq Aue qeyq pue g uotado 
ZOF O= 7OS Eq SIT TTS 7eYR pepueumoDer 
ST 3I “quTod styq ye Atuo py uopydo z0z 
peutsep eze esey, “seept orngnz jueweTduy 
03 pesn eq ues Avy os C= Res OTe AsSeT 
ey3 3nq ‘peTstTjuept eze 9 ATuo jueseizd aw 
*g pue p=suotjdo Aq pesn satq uotado z¢e 
*quesezd qe pesn jou ‘e7kq peg 
(ewezz snotaezd 
Ate yetpeumt eyQ AztTpou ptnom eyjep eurerzz 
ezeym suotqeottdde Tetoeds xrozy T= Fo 
SONTEA MOTTE OF SF STEY QuUSQUT UTeU sy 
‘yoeq souwezy u seqeotTput u= * (futrezznq 
eTqnop z0F) yoeq souery OMZ SReOTPUT OF 
sqrtnezep o= ‘Ax tTpow of st e3ep sty yoeq 
seuezy Aew moy seqeotpuy - zezy Os pesnun) eaeeTIEQUT 
( (208 09/T) seTtzsztl 
ut - peAetdstp sem owezy snoytaerd 
eUT I OF SATQETEZ euezz r0z HutwT3) eutTqTez 
((2es 09/T) seTszte ut - pexetdstp sem 
eUeTy YSITF SYR SWUTQ SYA OF EAT_ETOT 
suezz © zoz BGututA - pesnun ATQuezIMNd) eultqsqe 
(xaoa ey3 Aq pqueseirdex eere 
zernbueqj0ez Fo uotTytTsod - ATuo epouw yzox) K'x 
(eqep pebueyo-un Azesseoouun 
ejeuTUTTS 03 AGOa eYy3 Aq pequeseidex eere 
eq3 Fo AyStey pue yyptTa - ATuo epouw wox) q's 
("jou ZF 
O= pue ejep st ereqs Ft T= 32S SF ATTA 
yore ezeym xseu euetTd - AtTuo epow wox) 


*(zeqeT peseeTez 

eq 02 sTTeAep) enbtuyoe3 uotssezduop 
§ ,WeYyezy OTTY rAOF peazesexr (,6, TFTOse) PL= 
(Aq2ed paty3) ¢ do cezeqs 9= 
epou eqteg TeoTqzeA ekg g= 
‘epou eyteq Buot/qxoys peztTezreuey p= 
‘epow e3Teq 34roYS E= 
‘epou eqteq Buoy z= 
‘epouw WHII wOX T= 
‘(KdO@ WHII Tewrou) ATQOezTp yes O= 

spoyjeu uoftssezduos ey, uoTqeredo azxan 


* (uotssezduiopep sty3 ystTduoope of seurezy ueeMjeq eUITR 

ybnoue st ezeyq se Huot os) owezy e sserdwopep o3 sexeq 3t Huot moy Fo 
quepuedeput yoeqheTd ey3 OXEW TITM STUL “SWTZ JeYQ OF SAT QeTOZ dn 
peddttz eq ueo ouwezy qxeu ey os ‘dn peddtty st ouwezy e ueymM onTea 
Zeuy SYA Tequewuez oj emNs eg “TENUEW TeuTey Wou SYy UT ZeUTQ e 

yons dn butaq3es go etdurexe ue st ezey, ‘ebtuy ey3 Jo ydnzzequt 

YURTQ TeoTAzen eyQ Hutsn peaetyoe ATtsee st yoeqKketTd WINW JO BbututL 


“WINW S43 JO 4sex eYA Fo Auepuedeput 4Tt HutytTpe z0/pue ATQuepuedeput 
uotqoes yore butketd sqtured oste pue setddoty eTdtqrtnw ssozoe sWINW 
Butaattds sqywzed sty, ‘seuezy Bbutpessezd ey 3 03 pepuedde Atdutys 
eze seuexy Sututewez ey pue ‘pezoubt Atduyts exe sewezy omMQ 4sSITF 
ey3 TOF SWHTI ey ‘seTTF quenbesqns BHutpeex uodn ‘eTTzF HSutpeese:zd 
ey FO souwezy OMQ ASET CYR OF TEOTQUepT ere eTTZ quenbesqns e jo 
seurezgy OMQ 3s5ITF SYA se Huot os peyjzoddns oste ere sWINW STTtA-TITOW 


‘euery puooes SYQ OF TEOTAUEPT st YOTYM ourerzZ AseT oyR AFFpou TTT 
aznoz owezy BHuypqeez> z0z eATep syQ pue ‘ (euwerz ASIF SYR OF TeOT{AUEPT 
ST YOTYM) TezFFNq vsppTy ey UT SF YOTYM SurerZ SET SYR OF JxOU OR 
KzyTpou TTTM eezyQ ewezy Huy eer ToZ eQTEp SYA eseo sty Ul “seTYyR 
ewezy wors Hbutqeedex Aq wtue eyy doot ATTenutQuoo ued euo (AsIzTF eyR 
worzg e3Tep e Hbuteq puodes oyQ pue WHTI Tewxou e buteq ysrtz eyy) sesedD 
Tefoeds eze soeuwezy OMQ ASITJ SYR SOUTS “OMA ASITF SYQ OF TEOTIUEPT 
seuezy OMA AseT oR Butyeu ATduts Aq peyonzysuop eq Aew swiny butdoot 


“yuny d¥Wo 
zeyjoue Fo eouezrINd;0 ey TTRUN sewerz TTe 03 seTTdde dewzoToo meu 
ey pue pegepdn st dewzojfoo zeqseu sty ueyQ ‘seurezy ey FO eUO UT 

szeedde yunyo aqyWD & JI ‘ewezzy yore TOF pesn eq prTnoys deuwroToo 
STUL “WETI TETITUT SY UT XUNYS aWWO SYR wWory qos ATTeTATUT eq 
PINOM YOTYM WINW erTQUe eqQ roxy Adex eq pTnoys deuroToD zeqseu ¥ 


‘@TTF S44 FO pues ey Of senuUTQUOD sseDord sTYL “META ORUT 
pezesgznq-eTqnop st ewexzy meu eyR pue (poyjeu YOX 3SITF SYR FO osed 
eyqy UF yUNYO AGOM EY Worz eRep YOX SUZ TO) eQep WITG eu buyATdde 

Kq zezgnq veppty eyy ut pewroy st ewezy Qxeu ey, ‘“ernpecorzd ours 
ey3 yaTM peXeTdstp st ouwezz yore qufod sty aw ‘“zeseNq (UEPPTY 
mou) zeYy_O ey3 03 petdos sft exnjotTd sty ueyL “META OQUT 4T zZeFFNG 
-eTqnop pue zezznq veppTYy eyQ O3UT eANQOTd WATI TeTIATUT S4Q Epocep 
asztz 03 st ‘senbtuyoe; uotssezduom [Te rox ‘eanpeoord Tezeueh eyL 


"entTea 03iq 

TeutHtx0 ayy TEATS YOU TT}M ozez Fo e374q e oF enTea e7Xq Aue Jo 
ZO SATSNTOxe ue se ‘pexoubt eq ued ‘uoumoo Area eq TTT YOTYM 
‘seqhq oxez Fo sunz 3eYR SION ‘pextTnbez uotzexredo z0-eaTenToxe 
ey Op 03 peTsTpou ATTsee eq ued eutqnozr butpovep-yybuetT 

-unz Tensn eyQ ‘epou yox eyQ Hutsn ueym ‘umoys eq of ouery 

qxeu ey3 03 eurezz ueppTy ey3 AzTpouw o3 pesn St STTF WINY SUF 
wWory e3ep sueTy eyL ‘“wWeyR ueeMjeq BHutzezznq-eTqnop pue ‘saocqe 
peuotquew se ‘szezgznq omy eztnbez AtTTensn TITM SHINY FO yoeqhkeTa 


FORM and Chunk Registry 447 


IFF Specification 


reznqonazys ejep BuyTMoTToy eyQ FO sqsTsuoDd yunyoO GHNY SUL SWINY 6buTketa €°T 
yanyd CHNW T°2 
sqeumrog yuUNYD 0°Z “MOTeq €°Z'Z UOTADes UT peuTequoD ere poyjeu sTyQ wo sTTeIed 


SOP 'WINV 90P'WINV 





*(seuetTd zt 09 dn zoz ueqqtTim ueeq sey 

epoo) seuetTdqtq ezouw z0oz Qewrosy eyQ Sutpueqjxe MoTTe 07 ‘’puoDes 
pue (3Tyeueq Aue Jo aq 03 weaord jou sey styQ ySnoyqTe) » 
uotqdo zoz epod yATM eTqTAeduoD AeYMeUIOS eq OF 4sSATGA ‘“suoseer 
[ereaSes TOF peuTejer erEM QNq pesn AOU ETE g FO es puocdes oUL 
*seuetd g 03 dn zoz eqep ey Of szequTod eze g 3SITF SUL 

*y uotqado ut se posn ore szequtod 9[ owes ey poyjeu styy ur 


G poyyeu 0x euTOg 7°7°Z 


-eBenbuet Atquesse 

UT pepoDd eq pTNoys euTANozr sTyQ FO ‘QseeT Qe ‘eTOD oYQ ‘poeds 
yoeqhetd aqewtytn zoq “T=mMu Hutqqes Atduys Aq uotsseazduoo 
Tequoztz0y eTpuey ATtsee ptnood euTyAnor euo sty, ‘uumToo 
TeOFATEA |YyQ UMOp O6 03 dTyXs 03 spXOM FO ATequmu ey se VeoTpUT 
MU OTQCETIPA SUL “YOK ZO pxom Huot ‘Aes ‘xox suopqexreqrTe 
eeu pue suTANor styA eAeoTTdez oj st suotqdo snoTzea oy 
qzoddns 03 Kem quetotsye Asou ey, ‘“uotssexduop yahuetT unz 
YATM uoTsserduod TeOTAIEA PIOM ATOYS TOF st SUuTANOT eAoge SUL 


{ 
(0) uwznqex 
{ 
{ 


‘mu =+ 35ep 
/++2QRPy, = 2SOPy 
} (+48 lezts>sio=s) xr0Oz 
} esto 
{ 
i++2Qep 
{ 
{AU =+ Qsep 
SBQePy = SOPy 
} (4+8/o>slezts=s) zroz 
} (0 > ezts) FT 
f+4+2Qdy = OzTs 
/4+4+429d,y + zqdeuetTd = Asep 
} (aaaax0 =i TIdy) OTTUM 
‘[e+t]eqepeatep + promegtep = 23d 
[t]eqepejrtep + pzomeqTep = e3ep 
/ ((¥] seueta<-wq) (. quom) = r34deueTd 
} (++ /qQdeqa<-uq>t‘/o=F) zro0z 


lI<< moyzegseqAg<-wq = au 
PIOMEQATEP (x ONOT) = B3epeqTep 


iysep,‘P3epx AYOM TeqsTbez 
‘mu‘ezts’s quy zreqstTbez 
fxaqdeuetd, ‘z3dy MOM 
FBREPSQTOPs ONOT 
‘Fury 

} 

‘PZIOMEQTOPy TYOM 

fuq, dewata qonz3s 

(pzome3 Top ‘wq) 3ro"usWLTAIeS 


*eutqnoz 
yoeqketd etdures e ut sf Aewzros styA FO osn eYyA Moys OF Aem Qs0q OUT 


90P"WINV 


*(yoeqketd oyQ ut jou ‘uoTqezeueb ey UT ETT 
seueyos eseyq ut suetqozrd e434) sqsTT ou ZO ‘sAsTT AUeZeFFTp eaey 
SXIEYRO STTYM sqsTtT erTeys seueTdqtq euos eaey pue Aouez 3eb prnoo 
euo ‘qDeF UL “AT FO STeMe oq USeAS Rou peeU epod yoeqKeTd eyA os 

suotqztsod [Te ut peqeedez st 3sTT 3eyR 03 TeqQuTOd eyQ ueyA ‘seuetd 
[le roxy srequmu/yeszzo JO Ast{T euo ATuo st exeyR FI “3StT e3ep 
sxequmu/j7eszzo eYR FO ATeAS EY OF STEqUTOd ere g RxXeT SUL * (seuetd 
g FO xew TeOTJeTOeYA e of dn) soeueTdatq ey Fo yore roZ eQep eyW 

JO AzeQAQs CYA OF szequTOd - ezoyseq se exe g ASITF CYL “ATeQS SYR 

3e szequtod Huot 9f eaey 03 ATAYSTTS petTFTpow st yunyO WLI SUL 


y poyjeu roy qeumog 7°7°7 


‘O= ST yUNYD eYyQ Fo seqkq ZE ASITF O4Q ut 
zejutod ey A ueyq ‘oueTd ueath e ut spzom pehueyo ou oeze ezeyy FI 


*sueTdatq ey3 Jo suotTqeD0T snonbtquos ut peosertd oq 

03 exe yotym (epou uo butpuedep sqzroys zo sHhucoT) spzom e ep 
snonbyAu0D Fo Tequmu peAeotTput eyA st yeyQR BHurmoT{Tog ‘“MoTTos 
3ey3 spz0mM ejep Fo Zequmu eYR seqedTputT pxzomM-yr0ys ButmMoTTos 
eyQ uSeYL *“7+3E8FFO SYR ST ONTEA OEQnTOSsqe eYyQ ‘esed ZeYQ 

url ‘eatqebeu st jeszzo oyR FT ueaTh st uot Aeqerdzequy puoves y 


*gidix0 03 Tenbe 

Jeszzo ue yRTM seqeuTuIeR eVep ey, “""uo os puy ‘uot yTsod 
3ey3 3e peoetd eq prnom pxzom eqep ButMoTTos eyQ pue requtod 

eY3 OF Peppe eq PTNOM yeszFzZo Axeu oyQ USeY_, “UoOTATSod 3eYR 

qe pesetd oq prnom pzom ejep butmoTToy ey pue AT O27 peppe oq 
PINOM AeszFO SYA USeYL ‘eueTdATq eyQ FO pIOM ASITZ EY OF AuUTOd 
03 (epou eyA uo butpuedep sHhuot zo sqzoys 03) rzequtod e 47eqs 
ptnom nok ‘euetd eyq bupAonzysuopex ezem nok Jy ‘spr0M TEYAO UI 
-euetTdatq eyq ySnozryq (eqetadozdde st xeaeyotTYyM) spx0M ATOYS ITO 
Huot uy QuewerouT o4Q seAeotpuT 3t ueqy eAT ZTSOd st QeszzZo Oy 
JI *Weszzo ue st yoTyM prom Huyqzeqs e Jo sqstsuoo dnoxh yor” 
“spI0m 3X0OYS ST BQep TTE Of sQr0Ys OsTe ere spi0M ejep ydeoxe 
Teotquept eze sdnoz6 ey ‘epou ejteqd Ar0YUS UI “eWep Tenqoe eqQ 
ZoF sprom HuoyT pue ‘szequmu pue sjeszzo TOF sprom ATOYsS - spioOM 
Huot pue yroys yW0Oq Fo ystsuoo sdnozh esey A ‘epou eqreq buoy 

url ‘spzom ejep go sdnozb zo systsuop euetd ueath e roxy eqep SUL 


* (butxeput eseq-orez oj enp ZE FO ENTeA xepuT) yAuNnYo 

eq FO 03Mq paz-EE OYA UF sSqTeQS EQeEp EYQ Se ZE FO ONTeA & eaeY 
TTUTM szequtod g esey3 BbutmottTos ATeqetpeumy Huy zreqs eqep ouetd 
ey rox zejutod ey, ‘seuetdqtq g o3 dn yo yore xox eQep eyy 
oF yunyo eyQ oqut szequtod e7Xq exe spxzom-HuoT g 4sITF SYA se 
seqkq Ze st AuUNYO styQ FO ezyts wumMuTuTW ey, “eVep uoTssezduioo 
BATSP e432 PTOY OF pesn Yunyo eA7ep ofseq e st YuNYoO STUL 


€ 3 f spoyjew zoz Qewzog [°7°Z 


‘yunyo sfyQ JO eAN_AONIAAS TTeTeAC EYQ AOF sqeuIOF 

DTseq omQ ere eTSEYR QUeserd AY “peQDeTes WeEUTOZ uoTssezduoD 
qoexe ey uodn juepuedep eq TTTM e7ep eYyQ FO WewrToOsZ ey “Ee Rep 
uotssexduod eATSEp PTOY of pesn yunyo eAep OTseq EYQ Ss} YyUNYo sTyL 


yunyo WLTId 2°% 


90P'WINV 





vices 


De 


448 ROM Kernel Reference Manual 


/+ Suymezp az 530 GI «/ (pyzEzZsrPxXo) azad 


/* AZad x/ 


fezts SNOTO 
‘ar SNOTO 
} qonz3swaoOgd 7ONTAsS 


/* Wiog & eze shuymexrp ITw «/ (ayzsav9vx0) Wiod 


syunyd dzdd euL 


*pezeeTo 


83TQ SAF TTS SET 00000000 FO ENTEA O4R WatM uotstoerd eTbuts azagr uy 


*peumsse 


ST euo ueqj-eseq HbutpeeT eyR ereym ’°° 666666 °T 
©23 0000000°T woxzz sebuez 4 ‘“esstQueEW 3Tq EZ EUR ST 
("zequmu gazaI ey o{UT AT Bbutyoed exozeq yueuodxe 
eq} OF PEppe SF LZT FeYR sueSU WIOF LZT sseozg) 
pestexr st essTjueW ey YOTYM OF OMA FO zemod eYyQ st 
zequmu styL ‘“wroF LZT ssooxe ut jueuodxe ATq g O43 ST 


“eaTtatsod 


8% © pue eaTQebeu st T oreYM requmu ey Jo uUbts eYQ ST 


[L_uuwuunuuw ua wuUuUuUUuUw uw uumumuuuwe eeee0 00 8 | 


IsMOTTOZ se pehHuezze 


"S3TQ ze FO 4STsUOD szequmu esey,, ‘“srequnu juTod HutTqeoTZ uwoTstoemd 
eTbuts gzqI se pez0qs ere WOT Azud SY UT pez0js sentea oyQ Jo AueW 


‘exznqnz zeeu ey 


Ut WUOd Meu sTYyR Aroddns 03 Bbuyuuetd eze woTyzerodz0p Hbutysttqna yxT5oT 
RyOS pue seTazqenpur uoxes ‘“roRDeACTg, ‘obeyoed Suymexzp pernjonz3s 
TeuoTsueuyptp-omA AEG TOF AYEWIOF STTF EATAEU SYA se OSM TOF “OUT 


‘atsette, Aq pedoteaep sem WuOd STUL 


“pfoa styl STTts WHOd Azad oud 


‘eTqtssoduy jou J} ‘QTNOTFITP St zesn eyW pue 

zedojTeaep ey3 qR20q zoz ebueyoxe ejep ‘pzepuejs e 3noyRTM “euo eThuts 
e FO peeqsut sprepuejs eqeatad [Tereaes puejszrepun 03 uoTAeoTTdde 

yoee senx0z Aq se sbhuymerzp az esn e493 suoTZeoTTdde zo yueudoTessp 
ey3 szeputy pzepueqs Suymexzp qz e Jo eouesqe SY, “pxrepueqs 

ebyuy ey se qewros ETTF SAT PEUSTTGeAse sey euou 4nq ouTQ SUloOS TOF 
eTqeTTeae ueceq eaey sebeyord HuyMerp [TeToremmoD Tereaes ‘euyy Huot e 
zZoz pepeeu ATezos ueeq sey shutmerzp az eqtzosep OF WHO AAI prepuejs W 


ZIQ uyor pue FFTuunD ssoy Aq uot Adtazoseq 


90p'dcud 


azad Waod 


qewzoy pxzepueqs 30efqo a-Zz 


jeuo Fo peeqsut mox zed sezhq Jo Tequmu eyy Ppe om 
uoTZeUuTAsep ey ut 2e3hq Axeu eYR 09 306 03 os ‘ATTeQUOZTIOY TeYR 
zeyqez ATTeoTzzEeA pesserduod st eAep ey3 7eYR put uy zeeq Od 
“seult2 qunos jeedez 03 entTea 03hq e Aq pemoTTos 
‘eqkq unos e Aq pemottTos e7Mq 0 & st styR - sdo oues “¢ 
*Kdoo 03 eqep ey Aq pemo[Toy eszrnoo. 
go s,ar ‘Attezeatt Adop 03 ejep zo seqkq Fo zequmu 
eqy JO AUNOD e st JeputTeweT eyy pue UMOp pexYseuU st 3TC 
FY euL “30s ATI TY eYa YQTM e3Mq e st styR - sdo btun “Zz 
*ozez-uou st 31 “dtxs 09 OT 
‘pzemz0z zequtod ,, Asep,, ey3 eaouw oj smozr Aueuw moy ses 
qeyy FeETO 3tq Ty oyg yaTM eWAq e st sty - sdo dTys “T 
:gsBTD yotys uo butpuedep ejep so qunowe 
Buthzea e Kq pemoTToy pue ‘sesseTo eery3 Fo exe sdo oyL 
‘ewery QSeT SYR WoOTZ wUMTOD sTyA ut ebueyo ou s,ezeyR 
sueew jsnf at ‘xo s,3eY3 ‘ozez st qunos-do ey3 JI ‘“sdo zo 
zequmu e Aq pemottToz junoo-do ue yatM sq4zeqs uuMTOD yoreg 
‘yore seqiq 00z JO suumTOD OY eae pTNoOm eueTdatq OOZxXOZE WY 
-Kteqezedes pessezduop st eueTdatq ey Fo uumToOD yore” 


isTTeqep ezow zoz (use*dmoosaun pue o-dytyxs) epoD 

8 ,WTC 03 zezez eseeTg ‘“Hbhutpxom-exr TouTU YATM epod s,jUey WTC 
wozz ATROeITpP uexey st poyjeu eyZ Fo uoT3ydtzosep HuyMoTTOF euL 
‘stseq euetd-Aq-euetd e uo peuroszed st uotsserduocep/uotssezduop 


*(quey utc Aq uteuog oTTqQna peptaoad oste) wse*duoosaun Aq peTpuey 
eq ueo uotssezduosep pue (juey utc Aq utewog oTTqnd peptaozd) 
epoo o-dtys eyq Aq petpuey eq ueo uotsseirduoo ‘euetTd yore 107 

“stseq euetd-Aq-euetd e uo peuzogzized st uotssezduopep/uoctssezduop 


20P'WINV 





FORM and Chunk Registry 449 


IFF Specification 


*zequnu 
styq B5uysn epeu eze sxunqo qzuq zey;0 Aq juoz styQ 02 seouerezoy 
*quoz styq 03 subtsse qzud zequmu eYy3 st PTSOTZ AIWUOT ALAN PUL 


Hf 
/* 3AOF EYQ FO oweu euL +/ ‘[p-ezts] ouren aWHO 
/* é8ZTIES CARY YT S90P ¥/ iF F20s aLxAaa 
/» eTeuozqzodozd 94t sI x/ ‘Teuotqrodozg aLzao 
Js 0 SAeMTY 4/ ‘Teed aLxen 
/x Aq peouezezez st Quoz ey dI x/ farquog aLxao 
‘ezts SNOTN 
‘az SNO'TO 
} qonzQsSNog 3ONT3S 


“@TOTAIE sTYyQ UT T0eAeT 

pequeuncsop st YOTYM WAOd INAO SYQ UT peUTJEep squoz sesn TOJDe,OCT, 
‘peeqsurl ‘squoz ebtuy z0oz jz0ddns epntout jou seop zoyDe~CTd = ‘“WAOd 
azua e43 UT pesn AuoZ e Anoqe uoTREWTOFUT suTeQUOD YUNYS SNOT OUL 


/=« (AUNYD SNOT LXLA Se eures) yunyo Quod x/ (€Sap4p9bxX0) SNOT 


*szeqstbez zojToo ebtuy 

03 XA{qoeztp puodsezz0D szoToD yuNYD aWWO e4Q Bbutumsse ut op siepeer 
WHII euos 3eYR SYXeAsTW ey eXEU Jou qsnu srepeer qzud ‘Aoernooe 4iq-pHZ 
UATM STOTOO sQt sez0js azuda esneseg ‘“Aqtsuequt entq eyQ suTequoD 
PrTy ayy pue ‘AqTsuequy ueerh eyQ suTequod yxeu eyQ ‘AQTsuequt 

pez ey4 suTeQUOD YoTYM Fo Asztz ey ‘seqXkq seryQ ssozoe peerzds 

ST ONTEA 3TqQ-pzZ SUL ‘“senTea ToTOD gDu atq-yz Jo Aezze ue st deyrojpod 


Hf 
‘[ezts]dewrotoo aizqa 
fezts ©NOTA 
far ©NOTO 

} qonzQsdvWWO 3ONTAsS 


“uotTqequeumsop WAIL 
ddI 0YQ UT peqTzDsep se YUNYO AWWO WAI S43 OF TeOTQuUepT st yUNYO sTYL 


/+ (dYWOD WATI se owes) dew roToD »/ (OSTParEerx0) aYWO 


0° T=8ztSspta5 
pazepueqs=edkzebeg 
enzTL=3Ter4I0g 
your=s3tun 


teze sqrnezyep 

eyL “ONTeA ATNeFep eyA uo Y,oeq TTeF prnoys repeexr qzuq e ‘butz4s 
eouezeserd xzetnotyzed Aue yo enuesqe eyR ul ‘“seouezezerd eTqtssod 
eu3 Tre eqeas ATaToOTTdxe of yuNYS styR ertnbexr jou seop Waod dzud euL 


zequmu jutod-Hhutyeo[Tz e st <zequmu> 
woysnd 20 ‘GW ‘PW 
‘ew ‘Sa ‘pa ‘TebeT ‘pzepuegs zeyqte st <edX3-a6bed> 
SsTeI TO enzy rTEeYRTS st <ueseToog> 
BotTd TO ‘wD “your TSeyATS st <edX4-4Tun> 


<zequmu>=ez TSsptz5 
<edkj-ebed>=edkyebeg 
<UPeTOOG>=4TeIT4I0g 
<odfQ-ATun>=s4Tun 


90p'dcHa 


teze sHutzqs peqzoddns AtTquezznd euL 
‘zepzo Aue ut zeedde ueo shutajs ey, ‘“Aerze [Jsyzozq ey ut ‘shutz3s 
poqeuTwrej-TThu TezeAeS FO UOTAeUSQeDUOD e se soouerzezerd ser0js azud 


if 
/[ezts]szerzg zeyo 
fezts SNOTN 
?aI SNOT 

} 3Onz3sTadd AONTAS 


“uoTQeUITOsUT AueUTOATAUS QUeQIOdUT SUIOS 
SUTBQUOD 4T esneDdeq pehexnooue st esn sqt ‘peztnbez jou st yunyo sTyq 
ybnoyatw ‘r0_DeACTg TOF sHhuyqqes eouerezerd sutequood yunyoO Mdd euL 


/» seouezezerd ofeg ,/ (6¥Z7S0S0SX0O) Midd 


*qogx ueyA zeqeezh eq prtnom dozzA 3nWG 
aubtux uey3 sseT eq pTNom 3AzJeTX ‘seZeUTpIOOD ueTseqTeED uT eTduexe rox 
fetqtssod eze suotyeutquiods zeYRO “woRQICd EY PIEMOQ seseerTOUT sTxe-ZK 

ey ‘30gx > do~x JI“ 3uUSTI EY peMoQ soseeZOUT stTxe-x 9YyQ ‘QUHTUX 

> AJOIX FI “uotTAeQueTIO s,j0efozad ay Atddns oste AoyQ ‘weqsis 
@\eUTpIOOD e UT AUeUMDOP eYQ Fo UCTATSOd pue ezts ey Atddns ATuo 

qou seqjeutpz005 eseyy, ‘“TeuroD AyHbTI TeMOT sat st (Q0ax‘3UHtYUX) AuTod 
ey A pue yoeford ay go zeuzop yzeT zeddn eyy st (doxx‘3yeTX) Autod euyL 


fqoax ‘qubtux 
‘doLk ‘3F°1X qaal 
/x 9T SKEMTW x/ fezts SNOTO 
‘ar SNOTN 
} QOnzasqHYd 3ONTAS 


*(peqseu eq ued saqzud) 

etsy azuad eyy so zekeyT ysowzeqno syA ut jueumoDop e ut esuo reedde ATuo 
PThoys pue perztnbex st yunyo stu, ‘“seqeuTprOOD (xX ‘X) UT JusUMDOp 
ayy FO sowerzqxe QYybtr remMoT pue AzeT rzeddn eyQ sutTequod yuNnYyoO qHad eUL 


/x zepeey butmeza »/ (yysyzspyxo) aHdd 


*queumoop azuda eB Jo seqnqtz33e TeqoTh eqtzosep syunys HbutmoTToy euL 


syunyo eqnqtz33qw Sutmezd TeqoTO euL 


‘syunyo eseyA ut punog eze sdewqtq pue ‘qx0q ‘suobATod 

-Butmezp dazud Tenqoe eyQ eqtzosep syunyo yoefqo “yYunyo eyAnqtz33e 
qoefqo ue Sutsn jes [Te ere AOTOD euTT pue ‘uzeqqed ysep ‘uzeqqed TTtF 
quezino ey, “yunYyoO eqnqtzaqe yoelqo ey sMOTTOFZ 3eYR (Ss) yHUNYD Aoelqo 
ey FO setqxzedoizd uteqze> yes oj pesn ore syunyo eqnqtzaqe yoelgqo eUL 
“syunyo eqnqtz33e Butmezp TeqoTh ut peutzep shuty jes eptm-queumoop 
Teotds; eze suzeqqed [TTF woqsnod pue ‘uotAewrosuT eqzeTed 

‘seouezezerd queumoog ‘Sbutmezp oy3 ut sqoefgqo Auew o 3 uoumiod ere 3eYR 
butmerp az e& FO squUeUeTe eqTzosep sxunYyD eqngTz33e HButmezp TeqoTh euyL 
*syunyo qoefCqo eyQ pue ‘sxunyo eqnqtzayje qoefgqo eyQ ‘sxunyo eqnqtz33e 
Burmezp TeqoTh eyA :sdnozh eezyq oqut dn uexorq eze syxunyo adzud euL 


90p'dcud 





Devices 


450 ROM Kernel Reference Manual. 


*sqoefqo ButATzepun etqtsta SbutaeetT ‘MopuTM 

e@ se 408 TITM uzeqqed eyq ut ,,seToy,, Aue os ‘sq0efqo butAtzepun 

yo do uo pexyseu ATuo st ITTF O42 2e4R OION “(a “HTa) ureqqed 

PTT? eyR worz edeys sat ,,SdtqT>,, 3T se ‘yqed buyddtTo e peTTes 

st qqed s,qnefqo ey, “petits buteq (5 “Sta) 3oefqo eyq sdetTzeao 

aeya azed egg st eTqtsTA st 3eqq uzeqqed peTT3 sty3 Jo wopyied ATuo 
eUL ‘“STQTsTA jou exe sexoq Bbutpunog ey ‘uteby -(q@ “5ta) sett r0CTS 
SATT woyj0q 03 doq ‘qyHTr 09 AzeT ebed oyR uo peqsed st eTHueqoez 
StyQ ‘qdeou0D ur ‘“Zesn eYQA OF ETQTSTAUT st (sesdTTTS omy SY) 
uzeqqjed oq butpunozans w ‘Sta ut umoys xoq butpunog ey, *(w *5Ta) 
qoefgo s,TTIag ey3 JO seonTea xX pue KX eWeTRxXe eYyA UC peseq xoq Sutpunog 
Tengqzta e© 3y Sutath ‘uzeqqed TITF eyz FO Ano ,,eTTA. & sexe azud 


[suzeqqed TITs - z eaznbt gy] 


*qoefqo 

243 YRTM peyetoosse (xoda ‘ALLY) sxUNYyo eqnqTzqqe yoefqgo eyR zo Aue 
sntd yoefqo azud euo Aq pemoTTOF st TIIG W “WHOd Azud peyseu e& eptsut 
yunyoO AszTzZ Sy eq Asnu YyunyO TIIG eyL ‘“sureqqed [[TJ seouezezer 
yunyo eqnqtz33e 30efqgo ULLW e43 YoTYM Aq zequmu eYyy ST CITItd 


‘ 
Hf 
/*x TUFF 243 FO AI +/ ‘aItT ta fin Co): tye) 
fezts ONO'TN 
‘ar ©NOTA 
} qonzqsTIIa qonr4As 


“yunyo TITa eyA Fo eTdurexe ue suequoD eTOTAIe 
STYQ JO uoTQDes yUNYD AoeLqo any eYL “sMOd ZU peqseu epTsut 
pttea Atuo st yunYGo styL “uzeqjed TTF e& seuTyep YunyoO TIA cul 


/» wre, 7ed TITF pequeyzzro-_oefqo */ (ovoveropxo) TILA 


“yunyo ea qnqtzr334e 

q0efqo ULLW 843 UT Jes ureQQed TITTF JueTIND eyQ 03 HbutpzroDDe peTITZ 
ST MOXIE EYL ‘“peeyMorzzre eyQA of petTdde eq ued uotje jor rzedord ey os 
qy6tz eyQ 03 Butqutod st yunyo Mouw &43 UT pequesezdez peeymorze ey 
3eyQ seumsse adzud “3uTodpue s,~ATdO S43 YITM sepToUTOD (0‘0) uTbTz0 
S,peeymMorze SYL “07 peyoe_Qe sT peeymorzze ey ATdO EY FO AuTodpue 
ey O73 PATRZeTEZT we_sks oQeEUTPIOOD SUES EYA UT UMEIP st peeymorre oyL 
‘sedeys seutsep dazud Moy syouotydtzosep e roxy syunyo yo0efqo xATdD/ATAO 
eyR uo uoTQDes eYyR ees ‘wobATod pesoto e wroz squtod esey, ~“edeys 

Ss ,peoymorze 943 euTzZop [] squTogmozzy Aezze ey A ut seqjeUTpIOCD eUYL 


*uzeqqed pesymorre sty eouezeyeXT [TIT ATdO ue 
yotya Aq zequmu eyA st GIMOITW ‘“eACdE souTyep# SEY UO peseq peEYyMorze 
ue ooetd 09 ATaO ue Fo (s)pue yotym seTstoeds pTetTz shetyZ euL 


‘ [Zs qufogqumn] squtogmozzy agaI 
i squTogumy TaoHsa 
/x peey morze ey FO SOUEN x/ ‘qrmozzy¥ TYOHsn 
+ 0 sXemte ptnoys x/ ‘oped aLxAGO 
/= enoge ‘» Mowmaw wory ‘sbelta x/ isbeta aLxao 
7eZTS ©NOTA 
‘ar SNO'TN 
} onzQsmouW 32Onz348 


/x qaTod 4seT s,ATAO SYR UO MOTTE Ue MEIC ¥/ ZOXO ISWT_MOMIW euTsep# 
/* 3uyod Asaztz s,XTdO 24Q UO MozTeE ue MET x/ TOXO ULSUIA MOMMY CUTFEPH 


90p'dcud 


‘yunyo ATHO SYR UO UOTQEWTOZUT 

STOW TOF STOTATE styQ ut re_eT YUnYO ATdO eyA FO uotyAdtxrosep 

ey eeg ‘squTodpue zTeYyR 03 peyoRgqe speeymMorze eaey ued (XTAO) 
suobAjTod uedo qzuq ‘uzeqq3ed peoymorze ue seqtzrosep yuNYS MOUW OUL 


/» uzeq3ed peey-mozze uy x/ (LGAbZSTHXO) MOUW 


“PTTOS ST SUTFT ey 7eYR 

sueeu 9 Jo seysequmn e ‘uotqueauoo Aq uteby ‘“yunyo Hswa azua e Aq 
peutzep eq jou prnoys uzeq3ed HSWd STUL ‘“STQTsTAUT ere sebpe eyA “e'T 
“,TTe 3e uzeqqed ouTT on, ueeu of peazesez st Oo GIyseqd ‘uoTqueauoo Ag 


[suzeqqed ysep - [ eznbtz) 


*sqeedez uzeqqed eyQ ‘uzeqqed ysep 

eyQ wey rebuoT seutT Toy 3eYR eOTION ‘se Tdurexe uzejjed ysep Tereaes 
smoys eanbtz BbutmoTqToy ey~ “Gg = ¢°Z x 0°2 yabuet Fo ueds , ,FFO,, 

ue Aq pemotTtos ¢°Z = G¢°Z Xx O'T YQbueT go ueds ,,u0,, ue sAaey pTNom 

o7z ‘O°T FO uzeqqed ysep e pue ¢°Z YIPTM FO SuTT eB OS ‘YIPTM SUTT EUR 
go setdtartnw eze qnq ‘yunYS Midd ey UT peTytToOeds se sQtun ouwes ey Q UT 
qou exe syybueT esey, ‘setzque Jo zequmu ueve ue oq Asnu ezey, ‘ueds 
11FFO\, US FO yQbueyT oyQ AzpToeds squowere xeput-ppo eTTym ‘ueds ,,uoO,, 
ue jo yybuet eyq Aztoeds squeuweTe xeput-ueag ‘“oeNnuUTAUOD TITM ure qed 
ey ‘Aexrze soyseq oy4 ut seTrque ero ere ereyR JI “ureqqjed eyQ Fo 
uotazod ,,3JO,, eY3 seTstoeds ([ queuwete) requmu puoses ey, ‘uzeq qed 
eyg Fo uotqzod ,,u0,, ey Fo yAhueT ey R st (oO QueweTe) Aezze ey ut 
zequmu 3saTz ey, ‘“ureqqed ysep Tengjoe eyQ sutequoo Aezze []seyseq ouL 


*xequmu sty 
6butsn epeu oze syunyo azudq zeuyjo Aq uzeqajed ysep sty 3 07 seouezezey 
‘uzeqqed ysep otstoeds sty o9 peubtsse requmu eyQ st arysed 


: 
Hf 
/x uxeqqed FFO-uo x«/ / [seysequmy] seyseq agar 
/» weae oq skemte prnoys »/ Ssoysequnn Laousn 
/» uzeqzed ysep ey JO CI ¥/ ‘arysed LYOuSN 
7ezTts SNOT 
?aI SNOT 
} 2onzAsHSWa 3ONzAS 


“eUTT © YQTM peqetoosse uzeqqed ysep Jyo-uo eyQ seqTzrosep yuNYO sTUL 


/* sebpe zoz uzeqqed ysep eutT x/ (8VESTPPPXO) HSvd 


“quoz eyy FO eueu 
eyy bBututequos Sutsz4s peqeutwre3 TION & st ‘[]ewen ‘PTeTF 3SeT SUL 


‘sytzes eaey sevop/Teuotyrodozd st quoz styq ‘sex z 
“sztzes 

eaey ou seop/Teuctyzodozd you st juoz styq ‘ON tT 
‘syyzes sey/Teuotyzodoid 

ST ZUOZ STYR FT MOUX 2,UPTP TOQTIM Gzad SUL 0 


rsenTeaA oseyR 03 Hutpzoooe jes ere Koy “eTqeTTeae jou 

ST quoy petstoeds eyA osed UT UOTANATASGNS QUOF TOF MOTTE OF peqeerD 
@zem suotqjdo omg eseyL ‘“sytTres sey QUOy sTYyQ FT seqQeoTpuT FT7eS 

pue ‘Teuotyizodozd st juoz sTtya JT soeqeDTpuT Teuotyzodorzg ‘ATTeotstToeds 
*quoz sty3 go setqzedozd ejeoTput spTetsy stTres pue Teuotyrodozd euL 


20p'dcHa 





FORM and Chunk Registry 451 


IFF Specification 


“MOTOG PEeASTT seuTZep# eYA OR Hutproso;e 
adtqaos xxeyy ey butTTeo szeb6t24 yeyQA uopTaoe zeTNoOTAIed eyQ seTsToeds 
PTETS sxoeatTtTeotddy eyz “Aem ouos ut oefqo eyQ seqetndtuew zesn eyQ 
UeYM STTeO TORDeAOTG AdtIoOSs xxeyw eyR FO oureu oyQ suTequoD []euenTddy 


Hf 
/*x TTBS OF DUNT xxeyw Fo oueN x/ / (yQ5ueTeueNTddy] ourentddy zeyo 
/yq6uejeuwentddy qazoys 
fsyoeattTeotddy yzroys 
/eZTS  SONOTN 
‘ar SNoTmTO 

} qOnz3sNUuLX JONnTAs 


/« MOTEq ‘soUuTyep# wor ¥/ 


"suotqouny xxeyw 03 sq0efqo 
Azad AUTT OF ToOADeEAoOT, MoTTe 03 ATTzeuTtad peqeezD sem YuUNYO NULX UL 


/x yelqo peTTorquon ATTeuzeyAx” +/ (3Z7S~S8SX0) NULX 


*xoq B5utpunog eyQ dn Bbutyeu seutT ey FO YAPTM SeyQ UOT AeTEpTsuUCD 

O4UT eXeQ seqeUTpIOCD esey, ‘“3ybtz zeddn eyQ st (xXeWA ‘XEWX) 
pue xoq Butpunogq eyA Jo zeurOD pueYy AFeET TEMOCT eYQ FO SQeUTpPIOCD 
2U2 ST (UTNA ‘UTWX) QuTOd eyQ ‘uegqsXs ejeuTpIOoD ueTseqreD e UL 


: 
Hf 
/* UIPTM euTT Sutpnqout «/ ixeWk ‘XEWX 
/x “qo zo xoq Butpunog x/ ‘UTWR ‘UTWX aaaI 
fezts ©NOTA 
faz SNOTN 
} qonzQsxogda 3ONzQs 


*yuny> mouy x0 ‘TITg ‘3elqo azud s3Tt ezozeq ysn{ szeedde yunyo xoad 
eu, “3oefqo azud © se TTeM se MOUW TO TITa © 03 ATdde ued yunyo xogE 
W  “WAOd SYR UT YUNYS styQ smoTToZ zeyQ yoefqo azud ey S5utpunozins 
xoq Butpunoq e Fo uotgatsod pue suotsueutp eyQ settddns yunyo xogd oul 


/* Wa0d Ut oeLqo axeu Jo xoq Bbutpunog x/ (epavzrzyxo) xoaa 


“squowhes eUTT s,ULLY STUR JO YRPTM EUR st YOTYLebpg “ut ore 

sq0elqo s,aLLy sty3 zeAeT ey FO GI eyQ suTeguos zeAeqTYyoTymM ‘squeubes 
SUTT SYA FO TOTOO eyA st entTea~ehp_y ‘“peey MOTTE ou eARY SXTdO 

‘QO ST PeeHMOAAY FI “STQATSTAUT Sq TITM seuTT os uzeq qed ysep ou st 
ezey3 7eYQ sueew orez Fo uzeqAQeayseq WY “sqDefGO S,ULLY STYUQ TOF peey 
Mozze pue uzeq zed ysep ey FO GI eyR UTeQUOD peeHMOIIY pue uzeRQQeaGYsSeEd 


/+ utol pezeatw +/ T UILIN_LC Sutyeop# 
/» sutof eUTT Op 3,u0g x/ QNON LC eutzop# 
/« sedky utor «/ 


rsenTea 
ANOZ eseyR FO euO suTeQUOD pTEeTF eYyL ‘“squewbes euTT Jo sebpe syQ 
Butqoeuuos ueym osn 09 utof eutT so eTAas yotym seutwrejep edAzutorc 


“yunyo TIId © uy peutyep uzeqqed [Ite & FO GI SYA suTeQUOD 

SENTRATITd ‘SLOECHO TA 03 Tenbe sy edALTITa FI “PTSTF ONTEATITA 

e432 UT pezojs st (YUNYD AYWD OYQ WoTZ) GI s,TOTOD AeYL “TOTOD e& YITM 
UT PETTTF oq PTNoYys sqoefgo eyQ AeYQ seqeDTPUT YOIOD LA “PETIT ROU 
ere sqoefqo s,xuNYD ULLY STYR JeYQ sueeU ANON LA FO enTea y “syoelgo 
s,yUnYD ULLW Sty uo esn OF TITF FO puty qeym setztoeds edALTItd 


90p'dcHd 


‘xOTULebpy AagI 
fzoKkeTyotya TYoHsn 
fen teaesbhpa TYOHSsSO 
ONTRATTITA Taousn 
/peeHMorIy aLzgGa 
fuzeqqeayseq aLAGQ 
fedkyutor aLzaa 
fedALttta ALAN 
7ezTs SNO'TN 
far SNO'TN 

} qonzTASULLY WONTYs 


/* YaPTM SUuTT 
/* ut s,3t reAeT FO AI 
/* xeput roToo sip” 
/x TIFF OF YUM YATM QDelqo To OTOD 
/» SN OF peeyMorzre Fo CI 
/* uzeqqed ysep ebpe jo ar 
/* moTeq ‘» Lf FO eUO 
/* eaoge ‘x Ld FO suo 


SLOGCGO_Ld SuTzopH 
AOTOO_LA euTzepH 

GNON Ld eutyzep# 

/x sedk3 TITF snoprea x/ 


/* sqoeCqo peTT3 YaTM TItd z 
/* e7QeTed WoT AZOTOD YAT TIT t 
/* TTtz ON 0 


‘qQsaTyZ seulod Teaeyotym ‘spue wIOA HButsoToue eyQ zo ‘seqnqtz33e 
ey sehueyd yLLw 3xeu ay4 TTQUN Aoezze ut Aeqs seqnqtz33e eUL 
"QT MOTTOF 2eN3 SsqDefqo eyQ TOF seqnqTzyAAe sNoTIeA sjes YuUNYO ULLW PUL 


/« seqnqtzaqze qoelqo x/ (ZSYSPSTPXO) ULLW 


syunyo eqnqtzzqu yoelqo euL 


“eTqtstaut eze qeyq szeket 

butytpe ATTequeptooe worzy resn eyQ desy 02 ST STYR TOF uoseer SUL 

“Qes Q0U ST BAILOW JT 3euR set duty 3Tq GEAWIdSIG JI pezeeTo y “weeros 
ey3 uo etqtsta ATQuezzno st zeAeT styR ZeYR SOQeOTPUT AT GEAWIdSIC JT 
qes Wo “peyootun st zekeT styQ ‘39s ST TQ FAILOW AT 43 FI 


AXAWIdSIG_@T OutzFop# 


/» weezros eyQ uo peXeTdstq x/ ZOxXO 
BALLOW JI eutzopH 


/= Butqtpe rox eat IOW »/ TOXO 


:MOTEq 

seUTsOPZ SY OQ HutTproODDe Yes Ere SATq S,OUM PTETF 3Tq & st sheta 
‘zeXeT eyQ FO oureu peqeuypw7ey TION eu st [JowenzeAeT ‘soqeotput 
eureu s,prTetsy euq sy ‘zeXeT styR O03 poubtsse requmu eyQ st qrzeketT 


‘ 
Hf 
_  /x 0 skemtyw x/ ‘oped aLxAaan 
/x MoTEq ‘yx aT worz ‘shea x/ isheta aLxaa 
/+ pepped pue pejeutwreq TINN x/ / [9 TJ] owenzeAeT zeyo 
/= TeKeT ey FO QI x/ ‘qrzefeT LuYoHsSn 
fezts SNoTN 
Head SNOT 
} qoOnzASsYAWI RONITA5 


*sebueyo Tequeptooe worzz sq0efqo s,zeXkeqT eyR Aoe 307d 09 zekeyT 

@ YOOT ues Zesn eyA ‘/osTy ‘“ueeEezoDs sYyy uo pepeseu ATQuezmns you sqoelqo 
zo Ketdstp Azesseoeuun eyQ seqeututtTe sty; ‘peAetdstp jou ere zeXetT 
ey3 UT sqoefqo eyQ 3eYA os ’,,zJFJO peuTNa,, eq ued xeAeT Te TNoOTAIed Auy 
*sernqeey [nyesn [Tereaes opyaorad szekeqy ‘szeXkeT eseyy FO suo ut st 
q0efqo azud yoeq ‘“szeXeT ezow zo euo oqutT dn uexorq st qoeford azud v 


/x zeKkeyt & eutzeq +/ (ZS6STPOPXO) MAWT 


90p'dcua 





vices 


De 


452 ROM Kernel Reference Manual 


‘[squyogqumnsZ] squtoghtoa aggI 
isquyoqumn TYoHSN 
fezts ©NOTOA 
‘az SNO'TO 
} qonz3sATIOd 2ONnITR5 


*queubes euTtT 

e JO squtodpue eyy exTT ‘Aeeu og eney Qou Op squtodpue s,uobATod uedo 
uy ‘yjed snonutquom e st 3F 3e43 Os uobATod pesoto e Jo sqjutodpue eyq 
Sutqoeuuos quewbes eutT e& sppe zeqnduiop ey A 3eyqQ st uob&Tod uedo pue 
PesoOTO e& usemMjeq eDUeTEFZFTTP EUL *(ATdD) wobAtod pesoTo eyQ pue (xTdO) 
uobAjtod uedo eyq ‘suobAtod azuq Fo sedX3 omy ore ezey, ~*suobktTod 

azua so setduexe [Te eze sore pue ‘seTorTO ‘sezenbs ‘seuTT ‘“WHod 
azua ey3 ut sq0efqo qz TITe ysouTe Fo squeuoduios ofseq eyQ ere suobATog 


/x wobXtod uedo x/ (6SD%0S4~x0) ATO 
/» wobkTod pesoto «/ (6SOPOSERXO) ATA 


‘ebewt eyQ putz oR ezeYM zesn SYA xse 

PInoys at / (Az0Q0ez2Tp Quezaznd eYyQ ut HutYooT) FTesqy eweu eTTF eyy ro 
eueu y7ed [Ins eyQ wo peseq ETTF WHTI we SAeDOT JouueD Jepeer qzud e& 
JI ‘weqsks zeyzoue uo WATI ewes eyQ of YQed eyQ youre jou Aew weqsts 
euo uo WATI ue of yQed TInz eyZ “Aoezr0D st yQed ey oumsse Jou 
PInoys sxepeexr qzud ‘“eTTF eyy O39 yYAed TInJ zo TeTAred e uTeQUOD osTe 
Xew pue eTty WHII ey FO eureu ey suTeQUOD YAeq “enTea sty ezoubTt 
Tit pue sdeuytq so uofjejoz azoddns ATQuezzno jou seop roWDepOCTg 
“xeuzop puey qzeT zeddn sqft punoze WHTI ey} eAeQOZ 09 seerbep Auew 
MOY STTOEQ WOTAeQCY ‘“peTeos eq pTnoys ebheut ey YOTYM 02 suUOCTSUOSUTpP 
K pue x oyq Atddns sprety eztsx pue eztsx eyQ pue deuytq eyA Fo rz9eur0D 
puey azet zeddn oyy Fo uotytsod eyQ st (sodax ‘sOqgxX) eReUTPIOOD SYL 


/« STTF FO YRed poqeuywzez-TInN »/ ‘(ue TyY3eq) W3Wea xzeyo 
/* Wed zp Fo yQbueT »/ fueTqWed TYOHsSN 
/» seexBbep ut »/ iwotqeqoy 
/s O8ZTS TENQITA x/ ‘OZTSK ‘SZTSX 
/* SPZOOD TENAITA x/ ‘sOdk ‘80axX agar 
} qonz3sWEA 2ONzQs 


‘ebewt WaTI 

ue zo eweu eTTF pue ‘suotsueutp ‘uotatsod eyQ sutequop yuNYo WEA SUL 
/* FeWATE TeN3QITA x/ (ozayzresxo) WaA 

“WIOT AZ7Ud SYR UF EeTqeETTeae sqDefgqo ey3 euTsep syunyo HutmMoTTosS eyL 
syxunyo qoefqo SUL 


0°2 O°2% GL°Y OTL LevsséT AZISTa uoftsueurq 


I8TYQ EATT uotsueutq adtzos xxeyy ey TTeD PTNoOM ro0RDe,OCTg 
’Z JO zoqoez Aq eaoge umoys Qoefqo NYLX EYQ pezTser Aesn EY FI 


90p"dzHd 


“yUnYS ULIV 
eyA UT punoz seqnqTz4je eYQ of sebueyo sqoeTzez ebessow FONWVHO XK SUL 


euweu Quoy ey st uz 
edk3 utol ey st aC 
ayStem ebpe eyQ st me 
xXeput TITF e494 St Az 
edk3 TITF Oud St 3s 
(xeput zoToD eHpe eyq) entTea ehbpe eyQ st ao 
(xepuf uzeqqed ysep ey) edky ebpe eyA st je 
*-Kteatqoedsez ‘suoTqoeztp TeoT{ArEA 
pue Tequoztz0y eyA ut szojoes BuyTeos eyq eze As pue xs 
peqejoz st 30efqo ayq (seezfbep ut) etTbue ey st eTbue 
peztsez zo peyeqjoz st ADefqo eyA yoTYyM punoze qutod eyq st (AD ‘xD) 
ZAOW IO ANOTID C43 FO WeszFO uopaysod ey st (Ap ‘xp) 
yeefgo sty 03 subtsse roqDeqorg 3eY3 GI 3oefqo eyQ st aIfqo 
shutizqs TeISERFT ere “D030 ‘AZISTA ‘ALWLOU ‘AAOW ‘ANO'TO 
qdtzos xxeuw eyQ Fo eureu ey st Tdde 


,,QIFqo anowonn Tdde,, anowonn_x 

1:GIfqo xaoDd Tdde,, xd00_X 

,,QIfqo ino Tdde,, mnao_x 

,,arfqo aLatad tdde,, aLaTaIq_X 

1:UZ 3C me az 3Z Ae © aIfqo FONWHO Tdde,, GONWHO_X 
As xs Ao xo aifqo azisaa Tdde,, aziIswa_x 

, ,etTbue Ko xo aifqo aLwziou Tdde,, ALYLOU_X 

,.Kp xp arfqo aaon Tdde,, SAOW_X 

.:Kp xp arfqo agnor tdde,, ANOTO X 


‘MOTE peqtzosep eze sre jeuered 

euL ‘3s eze (s)5etz yotym og butpzosoe spues rzojDeporzg (s) Butz 
3eyM smoys astT ButMoTTos ey, *30efgqo eyQ 03 seop zesn ey Wey uodn 
spuedep spues roq0eg0rg ATQoexe jeym “A0efqo styR peaou xo peztsez 
Zesn ey3 JT uotsueutg peweu Adtz9s xxeyy ey TTe®S pTnom roADe,orTg 


{ 


{ { s°s ‘s"8 ‘s"s “g } ‘2 } xxx ATaO 
{ n0°En ‘y ‘0°O ‘0°S ‘0°9 ‘O°T ‘S*O ‘0 } ¥XXX LXLS 
{ 2 } xxxx anus 
} dzua xxxx WuOd 
{o0°0 ’o ‘g ‘0 ‘T ‘O 40 } XXxXxX ULIW 
{ ,wotsueutd, ‘OT ‘HAOW X | BZISMTa X } ¥XxxX NULX 
} azua xxxx WuOg 


:qoefqo NuLx eyQ ueaTh ‘etduexe 10g 


/+ pednozbun ueeq sey joefqo eyL OOTOxXO  dnowoNn xX euTzep# 
/x pxzeoqdtTo = 

243 093 petdop ueeq sey qoefqo eur 0800x0 ka00 X euTzepF 
/x pxzeoqdt{T> ey 3 ut pezojs - 

qnq ‘peqeTep ueeq sey qoefqo euL ovoox0 zno_x auTzop# 

/x P&A@TEp ueeq sey yefgo eqL 0Z00x0 aLatTad x eutzep# 
/» pebueyo sey joelqo oe 

43 JO (ALLY S85) egnqTz33e UY oT0Ox0 GONWHO_X eutzep# 

/« pezysez ue\eq sey q0efqo eyL 80000 aziIswa_x eutsepH 

/* peqeqoz useeq sey qoefqo eyL v000X0 ALWLOa_X eutzop# 

/* peacu ueeq sey 3o0efgo euL Z000x0 AOW_X eutzep# 

/* peuoTo ueeq sey yoefgqo eu, +/ TO0Ox0 @NOTO X eutTzep# 

/« SyDeqTTes ydjtzos xxeyw roxy sheta x/ 


90Pp"dcHa 





FORM and Chunk Registry 453 


IFF Specification 


{ 
‘() q3eaexyor3s 
} este 
{ 
SQ a3eattta 
} ( ATaD == aI )3TF 
/« Ged AseT CYR S80TO ¥/ 


{ 
/quewezourl =+ F 
/x WAeWeTSUT SCY PPY +/ 


{ 


/T = QuewexzouUl 


‘0 = quyodaszta 
2( (0 + Faz] equtoaktoa ‘[tz] squtoaktoa )OLeuTT 
este 
2( (1 + Faz] squtoaktoa ‘ [tz] squtoaktoa ) OLEACH 
( qutodqsazta )3T 
} este 
{ 
{ 
‘py =+ QueuerzoUL 
/* 83uTod TorQUOD eyQ ased qQueuwexzoUL ,/ 
0 = Quyoaqser ta 
1( [6 + Faz] squtoahtoa ‘[8 + Taz] squtoaktoa 
‘CL + Faz] squyoghtoa ‘[9 + Txz] squtoaAtod 
‘Ig + taz]squtoaktoa ‘[p + Taz] squtoadtoa )oLeazrnD 
( [e + Faz] squtoaktoa ‘[Z + Tez] squtoaktoa )oLeutT 
este 
( Le + Faz] squtoadtod ‘[Z + Taz] squtoakTod )oLeacw 
( quyoaqsata )3T 
/« squyod TozrRUu0D oTqno zeyzeg exe squyod p qxeu eyL x/ 
} ( gAuOD GNI 9 SaTqQ° Tduez 


iT = qutoaqssta 
*Qqqeamen 
/x qed mow oyQ dn 309 / 


{ 
‘() q3eaexorIS 
} este 


{ 
‘(uaeattta 
} ( xa == aI )3T 
/« @yetrdordde ZT ‘ITTF PUe SBOCTO x/ 
} ( OLHAOW GNI 3 S3atq*Tduez )3T 
?T = Queuexzour 
/* 1OAeOTpuT eyQ ysed queuexzoUL »+/ 
} ( MOLWOIGNI == satq*oduez )3T 
I(T + Tez] squtoadtog = umu’Tduez ‘ [tz] squyoaAtTog = umu’oduez 
} ( squyoaqumyn > F )eT UM 
‘o=T 
/* Uzed eyR werd x/ 
‘T = quyoaqsazta 
‘()yqeaMen 
/« Wed eyQ ozTTeTATUI »/ 


fquewezoul ‘Tt ‘3uTOdyszta qut 
/{duwez ‘oduez pxrooep 


90P'dzcHa 


(OLZAOW GNI | B3AUND ANI) = B5etz eyR Fo ontea 

ey3 ‘et ‘uobAtod-qns e pue oTqno z0eTzeg 

© HLOG FO AUTOd yszTZ SYA eq 03 eQeUTPIOOD 

HuTMoTTOF ey3 seqeotput ajutTod woOLYOIGNI 

ue ueYyM esed oYW eztTubooez 03 TTeF 02 uSEeq 
sey azud 3r0ddns 03 sqdueqqje ut [TTes3tTd uoumios y x/ 


200000000 OLAAOW_GNI euTyopH 
T0000000X0 ANITdS GNI outyop# 
FATAIIITIXO UOLYOIGNI eutyzopH 


ipz00p { 
83TqQ SNOT 
sumu gaat 

} uotun zepedxy 


iqeuxos eures eyQ esn [Te squUOZ 
eUTTINO s,TORDeAOTA pue ‘sMOUW ‘SKTdD ‘SATdO ‘“suobAtod azuda zo yeur0s 
SYR SAeTASNTTT OF uyATrobrte Hutmottos eyy pettddns ‘our ‘utsetTe, 


“SUOTRETNOTED SYA UT peeptTsuoo ere sqoefqo rey 0 

ou os ‘suobktodqns syt pue uwobAtTod e 03 eTnz ppo-uevae oyQ settdde 
ATuo qzud ‘“peTIts eq pTnoys pue eptsut st jutod eyQ sueeu shutssor 
JO zequmu ppo ue ‘ATeszeau0D ‘“peTItF eq 3,upTnoys pue joelqo ey 
@eptsqno st jutod ey ‘ueae st requmu ey JI “sessozo Aex eyQ squeufes 
yqed zo xzequmu eyQ Butqunood pue qutod 3ey4 wory pzemqno Kez e B5uymexp 
&q uobktod e ,,aptsut,, st qutod e ZT seuTWIe Zep eTNI ppo-ueAe syL 


‘@[NI ppo-usae eyQ Hutsn euop ere STTTF dz7uUd SYA ST PSTTTT 

st uobATod zeqno ey ueym dn pezeaod 3,ust uobAtod zeuut eyR uoseex 
SUL “3T utYgta uobATod zepTnozto zeTTeus e yQtm uobAtod xzepTnorTo 
PETITE © ST .,O., CUL ,,0:, FORQST OUR ST eTOY e YQTM uobATOd e Jo 
etduexe uy ‘suobAtod ut setoy eqeezD 03 eTqtssod qt exeu suobxktTodqns 
-uobAtTodqns sy pue uohAtod e ueemqeq uotqDeuuCD que qiodut 

ue st ezeyq ynq suobAtod zeyjo worz eqerzedes ATeqeTdwop eq oj xrzeedde 
Trtm uobAjtodqns sty, ‘uobAtTodqns zo ‘uobAjtod mou e sqreqs (squtod 
uoT_Des OTqnD Fo Aes zo) Autod eyR ‘Aes st AatTq sty JI “Het OLIAOW 
ey3 ST PTETF 3TqQ s,QuTod roJeoTpUT eYQ UT ATQ TepIO AsemOoT puodes EYL 


“uoTQD0es 

Dtqno e dn exeu qutod zoqeofpuyt ey MOTTOF 2eYQ sgquTod oeyQ ‘yes 

ST ATT JEpIO-MoT s,PTOTS IFA STUR FI “PTOTF 3tq & ST enTeA XK s,QuTod 
XORVOTPUT SUL “AddsIIIIIxXO JO enTea xX ue sey Qutod roJeoTpUT UW 
‘@eAIND & eqTzDsep AeYW squTod ey worzz jutTod [eurou e e_eTQueTesstp 
03 squtod uotj0es oTqnd Jo jes Be erozeq AuTod zoReSTpUT Ue syqresuUT 
azaaq ‘sjutod Teurrou ey Fo seqeutTprooD eyy yatm Aezze []squtogktod 
eYyy UT peTojs exe UOT QDes OTQnd eYQA HbutTqtzosep sejeUTpIOCD eUL 


‘pa 2e spue At oreym ‘uoTQDes OTqnD eYyQ oF QuehueQ st Fd OF Ed 

wory SUTT PUL ‘“AuTOd ysaTF ey Ae eATND SYR OF QuebueQ st (Zd OF Td) 
SAeUTPIOOD puoDes SYR OF ASAITZ SYR WorZ SUTT EYL “suTHeq eamNnD SYA 
ezeym qutod ey4 st (Td) eq_eUTpIOOD AsatTz eyLZ ‘“euTTds otqno e zo edeys 
ey seutzep (pa ySnozy3 Ta) seqeutpzroop aznoz zo yes y ‘suobXATod ut 
searnd eqtzosep o3 ‘seuttds otqno zo ‘suoTqDes otTqnD rzeTzeg sesn qzud 


[seazno zetzeg - ¢ exznbtg) 


*seQeUuTpIOOD ZK SIS squEUETS xepuT ppo eYyA pue seqeuTpr0cCD 

X ere sjueuweTe xeput uene oy, ‘“suobAtod go sqzed pearno-uou eyQ 

JO squfod ayA Fo seqeutTproo> (x ‘x) eYR suTequos Aezze squtogATodg e432 
pue uobAtod eyq ut squtod so zequmu ey suTequoD pTeTF squToqUmN euL 


90p'dcHd 





Devices 


454 ROM Kernel Reference Manual 


{ 


“ezts quoy K pue x ue 03 eTqezeduCD 

@eze SpTetF H/MASYUD UL *qybtey zeqoezeyo ebereae ey st HzeYD pue 

YAPTM reqoezeyo ebexreae ey st MIBYD “WOTReQOT zeqQze 4xeq SYQ SeTeOS 

[butmezp azuda etduts - y exznbhta] O34 pesn oeze HreYD pue mzreyD ‘“qybTr ey OF Seaow pue (Keseg ‘xXeseg) ye 

@qeutThTio [TTA euTTeseq s,34xeq syQ ‘(seerHep) orez st pTeTy uotqejoy 

ey JI «“pezeyzor st 3x03 SYR YOTYM punoze qutod oyA st sty, * (AeseE 

‘xeseg) st 3x03 eY4Q FO eUuTTeseq eYyR Fo AuTod Supazeqs eyL “XunYyO SNOd 

e ut 4eS ST GI §,QUOF SUL “QUOTYOTYM ST QxXeQ eYQ AepuUeT OF pesn QUOT 

{ o°z’o°2% ‘0°9‘0°% ‘0°9'0°8 ‘0° zy xTdO ey JO GI ey, ‘[]szeyoqxe, ‘Aerze zeqoezeyo eyQ ut st Sutzys 4xe3 oUL 
{ 9T xoaa 


uPTZOM ‘OTTOH, “ZT ‘0°O ’0°S 9€ LXLS i{ 
/ [szeyoumy] szeyo xe, zeyo 


7 szeyounn LYousn 
/» (seezbep ut) 3xeq Jo eTbuy x/ FUOTIEION 
/* euTTeseq Fo 47eIS ¥/ ‘joseg ‘xeseq 
/+ TeYD TeNpTAtTput we JO H/M x/ ‘HazeyD ‘MzeqD agar 
/* ©5N OF QUOT YOTUM ¥/ FQuogyoTuM aLAaN 
/* (uotsuedxe ezngnz x03) 9 skemtw x/ ‘opea aLAqa 
fezts NOTA 
‘aI SNOT 
azuq } waod } 32NIASLXLS WONT3s 


tWaod azua (oTToquAs) e st ezeH “Qx8Q SYyQ Tepuezr oF STSYyM pue MOY 
uo uotqeurosut euos yqtm BHbuote SbuyrzyAs yxeW & suTeQUOD YyunyoO LXLS euUL 

etduexg dzua eTduts w 
/= 3x03 eTduts «/ (yS8SPSESXO) LXLS 


-uobxktod azud eB Jo 

squtod eyA se jewroy ewes oy3 ut eze []yReq JO squtod eyL ‘“pezepuez 

jou st sTesat yjed ey_ ‘pezepuez st 3xeQ ey3 yotym Huote yqed 

euq st []uzeq ‘“Aerze []y3ea eyQ ut squtod Jo zequmu eyR st squToaumN 
‘pezepuez eq of 3x03 ey Sutupequoo Sutzys eyQ ‘Huyxzys [] szreyoRxeL /x syoelqo Z uATM ang wv 
eYy UT sreADeTeYS Jo Jequmu ey A st sreyouMN “eat ReEbeu oq Jou ysnuU /» WIOF peyseu Teyjoue TITI3s 

MzeqD 3273 ©70N ‘“UMOpeptsdn st quoz eR ZeYQ seTTduyT HINO” eATzebou 

vw ‘AjTeatqoedsez ‘sezts jquoy K pue KX OF UTYe ere pue szejQoerTeyo 

quoz ey3 so 3yHtey pue qyaptTM ehexzeae eyQ ere HIeYD pue mIeyoD 


/* YWed ssozoe qxeq peerds y/ €0x0 avauds_c eutsep# /x sqoefgo ¢ go dnozb w iqwx/ {i € ’ 
/* FXOR T0EQUED «/ zox0 UTLNIO_C eutyzopH /~ WIOF peysou Teyjoue 7X »/ 
/» peTztasnl aqbta x/ TOxXO LHOSTa_C eutszep# 
/=x Petstasnl 4zeT x/ 00x0 LIZI C eutyeopH /x Welqo T ATUO YRTM x/ 
/x eTQeQ urEQIed-TITS OULD WW x/ 
rsentea HBbhutmMolt[Toy eyQ FO euo eq ued uoTAeoTFT ASL /x “"‘wzZ0OF peqsou Ww x/ Wwaoa 
‘@UTT SYR UO peTFTasnf sft 3xeQ SYR MOY STOTQUOD UOTIeOTITIASNC sNoa 
"qx03 eY4Q ASEpueEZ oF pesn QUOZ eYyQ FO CI SyQ suTequodS AUoTYoOTUM /» ‘**sButyq zeyqo snoqzze, »/ duno 
/x %anyo quad Jo eoueserd Aq peurzzzuop x/ ania 
if /» *‘*Buymerzp TeaeT-doz x/ azadq } waog 


/= S®TT 3x03 OYQ YOTYM uo yQed eyL x/ /[sQuTOguMNyz] qed agar 
/+ i# NIAZ OL avd «//[szeyoumy] szeyojxeL xeyo ‘yunyo (TIIG pue) anap ey Jo 
/« yyed eyR ut squtod zo zequmNn »/ ‘squyoaumN JUOHSA qnokeyT ey3 seqerqsnTTt eTduexe HutmoTTos ey; “ang eyy UTUATM sqoefqo 
/x Suypzy4s eqQ ut szeyo Fo TequmN x/ ¢szeyoumn <ZuoHsn yo zeXeqT eyQ septzzeac WuOd anu eq zo reXeT yA ey sqoN ‘“dnozb 
/* zeqo TeNpTaTput ue Fo H/M x/ fuzey ‘mMzeUD @agI SFYA UT peuTequos sqoefqo zo zequmu ey suTequoD pTeTs sCqoumn eUL 
/* 28N OF BUOF YOTYM »/ fquogyoTyM  gLxGN 


/* MoTeq ‘souTzep ees ,/ fuoFAeOTFTASNC LAGNA f{ 
eves -anoan ‘sf qounn Mousa 


*ar SNoTO fezts SNOT 


} qonzjAsHLaL 2onITA8 ‘aI SNOTOA 
} Qonzysanowd yonzT4As 


‘yqed ey so ehpe eyQ Bbuote 


zepuez 03 butzys e settddns pue (uobAtod) yjed e seutyep yunyo stuL “waod 979 
Uy YyuNYo Asazty eyR eq Asnu pue ‘sWHAOT A7TUd peyseu SpTsuy PTTeA Tuo 


/* qqed e buorte butz3s 4x03 ¥ »/ (8~pySOSPSxO) HbdL st yunyo stuL "eUuo OFNUT sqoeCqo dazud [Tezeaes seutquos yunyo qnyd SUL 
/x GnozD +/ (oSsSzSLvx0) anus 


90p'azHa 20p'dcuHd 





FORM and Chunk Registry 455 


IFF Specification 


-suobXtod qzuq Sbutqtzosep ut pesn eq jou pTnoys pue 

WAOd BNAO YR 09 Atuo Atdde syqtq omg SseyL “SUTT eYR FO seqnqTz3z37e 
Zeqy_AO TerTeEASeS se TTOM se ‘OUTT SYA FO YAPTM EYQ seqQeQoTp yunyo 
8,ALLY Quezind ey ‘“pezepuez eq pTnoys FTEs {tT yqed peutzep ATquezzno. 
242 JEU SEREOTPUT ATC DIOULS GNI 39s WY (NUNYO ULLY JuezzrNS 

ya ut petTszyoeds se) uzeqqed [TTF WWeTINS eyA YITM UT PETITZ st yRed 
peutyep ATQuezinS eyA ‘Aes St 3TqQ TIIG GNI 949 woym “peyorjs zo/pue 
PETTTS reqate st qqed eyy TTAUN EeTqTsTAUT suTeWeT YAed QueTINS SUL 


*squosy 

Huyzepuez ueym yjed Auezino ey A Tepuez of MOY eqTIosep seUTyJEp OM] 
esey; *(eacqe seuTzep ees) s3Tq TIIA GNI pue gIoULS GNI ey3 ‘s3quTod 
zo4eoypuy uobAtTod uy punoz jou squtod rojeoTpuT Auoy uy pesn szTq 
B21Axe OMA ETS ETSY, ‘“SeTQTssod seyor3s pue sT{TTF eyeu of saTQeuUrSRTe 
ue pepeseu 4t ‘yUNYS YLLW ue eAeY AOU SEOP WACO INAO SY Ssnedseg 


* (ST FeISP 

OJ KIdO/ATaO FO uopadtrosep eyA ees) suobATod s,qzuq eutsep oF pesn 
poyjeu cures oy3 Sutsn poutzep eze seutTTANO INGO “Te_oereyo HBuyMoTToF 
eyQ TOF euTTeseq eY4R OF JoeszFO OY ST (UIPTMA‘UIPTMX) “ONTeA 

Atq-9T © se pezojs st yO ‘HUNYO NUTW SUR UF ZYD PUe TY SATI “seuTFEp 
YUNYD sty SUTTANO reQoDeEzeYD eYQ JO (IIOSw ATTewrou) enTea eyA st YO 


TIIG_ANI eutzep# 
TMOULS_GNI eutzopH 
OLZAOW_GNI euTyep# 
ANITdS GNI eutyzop# 

AOLWOIGNI eutzopH 


80000000X0 
v0000000X0 
200000000 
TO0000000X0 
FAALILLAIRO 


/+ aed snotaezd TItd +/ 
/+ wed snopaerd eyoras »/ 
/» Krodqns meu 37eI4S »/ 
/x 83d TorquoD euttds eze sqd p 4xXeN x/ 
/* WoTQOe ue St X “MOLWOIGNI == X JI x/ 


90p"dcHa 


F 
“{ 
/* squtod Tengoe ey x/ /x [SQuTOgUMNsZ] squto4g SagI x/ 
/* K - SutTeseq uo TeYS Qxou TOF uoTATSod x/ SWAP TMA 
/*x X - SUTTeseq UO TeYD RxXeU TOF UOTATSOd x/ ‘UIPTMX waar 
/x UOTATUTFEp eyQ ut squtTod zo zequmu eyL x/ ‘squTogUMN 3704s 
/x (IIOsy) Sututzep er,om TeRoOeTeYO OL x/ Wd -qzoys 
} OnzAsgZqHD 7oNTQS 


"squoy eUuTTANO s,r0RQDe~OCT, Fo edeys eyQ seuTsep yunyoO styL 


/* VOTATuUTZep reqoeTeYD »/ (9bPPSPEDxXO) dH 


“ZYD OF TUD wors asTys euttTeseq eyQ Atddns ‘enetdstqx pue eoetdstax ‘sptTets 
Hutuyeuez ey, “STQeTIeA ATQ-9T eB OQ eNTeA 3TqQ-g ue butubtsse yATm suetqoad 
ptoae 03 Aytzedoad subtsse ysed 03 ezns eq TTT xeumrexhorad Azem ey, ~“sentea 
atq-g se pezoqjs eze szeqoezeyo ‘ATTeUION ‘“ONTeA ATq-9T & Sse szeQoeTeYo eyR 
SOI0RS INAO 3243 SOTION ‘“seEpod IIOsw se pezoys AtTeotdky exe sreqoereyo 
eseu, ‘“UTEeX OF SsTEQDeTeYD Fo ated syA uTeEQUOD spTeTF ZYD pue TYD SeUL 


/+ dn+ umop- evertdstp oj Qunouy «/ faoetdstax 
/» 24STI+ 3FET- eoeTdstp o9 Qunouy «/ ‘eoetdstax @agI 
/* (°°°S3TQ 9T TOF smoTTe) urex oj ated oy, «/ ‘tuo ‘TUD yxroyUsS 
} QONIAGSNUTW FONnIQS 


*szeqoezeyo go ated ofztoeds e usemqeq eoue {stp 
eyy sqes ated SBuyuzex yw “ated BHButuzex e seqtzosep yuNYO NUM euL 


/« ated buyuzey »/ (ovzsspapxo) naz 


“YQPTM zeqjoezeyo ebezeae oy st YAPTMQUOT pue 

‘euTTeseq ey MOTeq QuUeDsep ehezeae sYyQ st QOgAQUO”, ‘eUTTesSeq ey eacge AYHTeY 
ebezeae ey st dozquog ‘“quozy styQ ut steqoeTeyO syA Jo suotsueutp ehezeae 
2YQ SeqTIDsep spTeTF TSAO SYL_ ‘“8sN TeVeT TOF peATesexr ere sytq repro reYyhTy 
pesnun ey, ‘sTzes pue ‘enbtTqo ‘ptoq eze ‘eaoge peutzep se ‘sbeTy oul 
“seqngqTz33e quos TereAes Tox sbeTF YITM PTOTF 3TQ © st srqqWQUOT “QUOT STYyR 
Jo oweu eyQ bututequoo Hbutz34s peyeuypwre A TION © ST PTOTF Swenquog eyL 


v000x0 aIWIS_Wa eutzep# 
Z000*0 ANOIITGO_WA Sutzop# 
To0OxO aod Wa SUTFOPH 


‘ 
af 
/* O 20330T EUR FO “O° ‘UQPTA TeotdAy «/ “UIPTMqUOT 
/~« SUTTESeq MOTeq Queosep TeoTdkL x/ ‘Qogquog 
/* euTTeseq enaoge qybtey TeoTdAy »/ ‘donquog  aaaI 
/x MoTOq ‘» Wi 28S x/ fszqqvquog yr0y4s 
/* pepped [Inu ‘oureu quog «/ /(zE] ouwenquo7 zeyo 
} OnzQSsqHaO ONTAS 


“quoz eyQ uO uOCTQeUTOZUT OTSeq eUlOS sUTeQUOD YuUNYoO sTUL 


/« TOACRSOHAQUOTEUFTINO FO GI x/ (yy8P9rdPxo) Hao 


“WIOF LNAO SYR UT peuTzep szuo;z 

oq ATuo szezex yunyo sNod s,dzua ‘azua e& wory eTTF eyeredes e st JAI 
STUL “INJO PETTeES WHOd ddI Ue UT peo JS eTe SQUOF SUTTINO s ,TOIeE/AOId 
/s OTTE YUOF OuTTINO JO AI #/ (ySap9vabx0) LNAO 


Wao0d LNAO SUL 


90p'dcud 





vices 


De 


456 ROM Kernel Reference Manual 


Buimeig GZHa aiduis - 7 eunbi4 


POM OTH 


SOAIND J9IZEg - € euNBi4 


90p"dcHa 


swayed jl4-- 2 eunbi4 
9 ‘big 


swueyed yseg - | eunbi4 
So=mpmouq [7 ‘¢ ‘7 ‘T] 


St=mMpmoug [9 ‘] 


T= pmsouq [€ ‘¢] 


90p"dcHd 





IFF Specification: FORM and Chunk Registry 457 


/~« pepuedxe ‘etaou Jo ezts WWU Jetaonzoezts Suot 
/» zequmu eqjetTed zoToo punozrbyoeq {zoToDAoe AUT 
/» STextd ut /qybtequeezDg AUT 
/*= sTextd ut ‘qqptmueezDs QUT 
/+ seuetd aq Fo requmu roy ‘9 03 0 ‘qqdequeezos jut /* punorbyoeq eseze 3,uU0p 0Z00X0 SNINLHSITZ eutzep# 
/» emery zed sq0efqo yo zequmu fewezgzegsCqo ut /x susezos pebed yj0q ojuT merp T000x0 GOWULT eutzopH 
/« yelqo zed sxeqreA Jo r9equmu S€qozedgsqutog ut /» euezy Kreve merpez 0000x0 TWMIONS euTFOpH 
} /x S@pour eurezgq y/ 
zepeep{UeZ qonz4s syepedAR 
/* /» wieg euerzzy 03706 z oLopdo eutyep# 
‘eyTaow ey Ut ae / 
spunos pue ‘souezz Auew moy ‘pepeeu st WWY yOonu Moy seuTzyep repeey sTyL ax » SouTq Tdez wreqg ewezy worz BHbutyreAs eouenbes jeedex t Iwaamudo eutzeps 
ae /» ewerz Axeu 03 Uo Ob ° LXgaNdo eutzop# 
- zepesy StaAou uoTtsTaequeg ,/ /x sepoodo ourezg ,/ 


(QHQNGLXG_AS4) (QUT) GEaNALXE3 eutTzepH fa ‘q qut 
(CaNITagaNnn_4s.4) (QUT) UNITYAANN: eutsepH } 
(OITWLI_aSa) (3Ut) DITWLI SuTsopF qutog qonz4s jyepedsq 


(atod 4S4) (3UT) atTod? eutyzep#F f{ 
(TWWAON Sa) (UT) 'TWWHONF fuoqqoq ‘ay6txz ‘doq ‘azeT AUT 
} 


eTkas qoey qonzqs zepedA3 
z LHDIUI out /* 
Tt UILINIOR eutzop#H s@ernqonzy4s uoTsTAeAUeY OSTW x/ 
° LIFIT3 eutzep# 

PERE TT CLT TEE CCCOTECOTITTTECCTOSETTTTT CCITT ESECCSSTELESSES SES OSS ST LL 
uotqeotstzenl /* ax 
ae ‘eyoty jAoCua xx 
edk3 uobXtod yootsLxaid ey3 Toy pesn ore esoyL «/ ae ax 
4e “ooze-z6y (Sty) st zequmu atey, ‘“ATAOezTp 4% 
/» ebeut deuwytq qasnf mezp x/ L adWNiiad eutzep# 4% SIEMAFOS punqzreporzg WoeQUOD Of peeu TTTM nok ueyQ 4% 
/» “TeAATA xx 4% quem nod quem st 3ey3 JI ‘setTaou uotstaequeg Aetd 4x 
Sutsn s,xeqzea Qe deuyqtq e Sutsn sjop meazp y/ 9 LOdaYNLIad eutzepH 4% ZO peotT of epoo Aue yAno eath ‘qoexquop Aq ‘jouueo> © ‘LON 4K 
/= “S8ZTS YE OZTSQOP xx we 4% 
Butsen s,xeqz0a 4e sqQop ezenbs sezp »/ S LoaLrogad eutzepe oe L62S-6b (STP) :eucud ne 
/= “®8ZTS JS SZTSIOP xx ** Pr 
BHursn s,xeQT2A Ye SQOp SeTOTFO meIp »/ v LOGAIONIOd eutyopH ae OZPZ-OSSP6 ‘WO ‘exrouTeATT He 
/* MBIp 02 YOOTA 3xXeQ »/ € MooTELXaLd eutzepH ax eatiq uuewebey Zee :TTeW sn ae 
/= tobkTod eutT peqoeuuos »/ z GaNITd eutzep# ae cae ae 
/» wobKtod sutT peyoeuuos-jou 4/ tT ANIId eutyep# 4% SeTeH Y eae qs j woo’ Teqr0d"dnojuns 4x 
/= vobXTod petty »/ 0 GaTIIad eutzep# 4% Yo woo" Teqrod*dnogsetTeH w eneqs :QeNe5n 4% 
/» (Ketdstp worzy peqetep s3t) TeTTTF eB st yoelqo +/ 000Lx0 @Lataqd eutzep# ae iskem BSuyMoTToy ayy ut peyoeez eq ued T ** 
/» 8edkq uobkTog «/ ae ax 
ae “Butsstu shuty3 mez eB ETB SeTEYQ SANS W,T 4% 
/+ sea e sey dewytq x/ OO0OTXO d¥WLIausnd eutzop# ax  3nq ‘eqetduos ATxzTez st sTYyL “ETT zepeey e se pesn oq ued *e 
/» “uot Aeutue Huyinp x» ae @Ttsy styL ‘“peez pue ‘Ano peketT ‘peqonzysuoo ere swyoOd-ddI er 
punoz6yxoeq ey OAuT peddozp eq {T1TtM wobATod ,/ o00zxo douaqnovad eutzep#e 4K moy FO ebpaetmoux eqeutqut eaey noA seumsse QI ‘“woTsTAequeZ a’ 
/= °23@ ‘/HUCTO ax ae ebtuy TOF pesn yeurrogzy eyR FO woTaAdtIosep e ST STUL a 
opts pztyq Areae TITM € ‘AVETA OPTS xx ae — STAITCAO ¥x 
puoves ATeAS EAPET TITM Z ‘Opts T2YQOATOAS xy ae 4H 
uo MEIP TITM T ‘septs [Te Uo sMeIP O “XO xy 4x seTeH eaeqs Aq pequeuerduy 4H 
“eUTT © JZoeUUOD Jou Of USEYM SUTUTEQEP xy 4x 4x 

02 eptsepomjod butsn uobATod peutT3no ¥/ ooorxo aNITENOd eutzep¥ ae - ee6et ‘Ss Aew aazoud Lwiod - 
/* apeyepes yoelgo st «/ 0008x0 Logtasd eutzep# a ae 
/x Ktod zo edXq ysn{ 306 09 yseu edk x/ 41i00X0 MSWWadALd eutzep# ** eazemqzos punqzeporg ss6T 3udTIXkdoD (>) ae 
/» sepou uob&Tod «/ 4H ae 
io ¥% ‘uotstaequeg ebtuy roy WeEUTOS STAOW FAI OY ST STUL 4 
/= S5uyzyAs peqeutwze3 0\ x/ saLS9, ULSO_AI eutyepH# ae we 
/= wobkTog & TOF OFuT Qewt0Og ¥/ sAKTOd, AIOd_dI eutyzeopH 4% YWTOTQUeT - xx 
/x owezgz © TOF OFUT ZeurO, »/ sAWES WWad_dI eutzep# ax »/ 
/* XOpeeH STAOCH x/ saqdHa s UaHA_AI euTzep# DOGO GOO OOOO OUI OUUIUOUGOOUUUUUUUUUUOUUUUROUUB EERE RE EERE / 

/» edk3 Wiod »/ sENW » INWd GI SutTzopH 

/* LNW Waod 


seuTseop WAOT UoTsTaAeque” »/ 
QeuIOy eTAOU UOTSTARQUeY 


9290p" LNV4 90Pp" LNV4 





vices 


: De 


458 ROM Kernel Reference Manual 


‘yom weo zequmu Aue ‘uotqouny 03 Ang 

‘oot JO set Tdt3rnu ut szequmu peubtsse st uobAtod yore ‘Sut qtpe 
buyazng ‘remeta eq3 03 st uobATod eyA resoTD eyQ zequmu eYyW zeyqdTYy 
eu_ ‘zepzo Aetdstp eyQ seutuzejep uobAtTod yoee Jo y dep meta oy 


*suzeqqed Fo jes 
peutzep-ezd e ojuyT xeput ysez eyy 4nq ‘sxOTOD gou Tewrou ere 


szequmu Ze 3SITF CYL “OZIT 03 O WoOrF requmu e st eQQeTed TOTOD ey, - T 


UREA ARAN MARIE NEE EE OR EE EE SALON annex / 


quoz FO oUeN aLso 

mooTaixaid = edXz~ktoa 3+ Atod zo jxeL aLso 
skToayozequmN seUt x'Tod 

*“Z [Teuueyo rAoF punos FT XaIgs 

"[ Teuueqo zoz punos 57 Xdas 


seuezasJOTEquMN seuty wwad 
- 3S57T ouezy —- 


punos zoz szejeuerzed atnezeq == { Xaas 
%GO@ 
aUdHA 


spunoszorequmN seuty XAS8 WaOT 
- 38TT punos - 


xqog 
Cane 
sdenatasozequmN set 3 WII WHOA 


*eut3 peot Bbutanp eqnduocs eq TTT AF ‘yseu e seq dewatq e JI ALON 
- astt dewatq - 


AGO 

CHW 
ozez-uou st punozbyoeg Jt WATII WiOd 
- punozbyoeq - 


aqua 


NWI Wid 


/* 


ee 


“qemzoz gar TeaeT-ySty woTstaEqueg ¥/ 


9290p" LNV4 


/* 8xeQz00 BHBututzep squtod zo Aezze x/ f(]d qutog 
/» wotsuedxe x/ ‘ped Bbuot 

feTAasqxez rey 

/* STexTtd uy ezts x/ feztsaxe, zeyo 

F4snc {xeL UT 

/* MOOTHLXELA Toz 9x03 FO yRbueT +/ fygbueT3xe] 3UT 
‘qqabTeHTeewNa 4UT 

/*= STOXTd ut x/ ‘UIPTMTeCUNA QUT 

/* 4StT dewatq oquy xeput dewqtq ueyq ‘T- 30u ZT ¥/ ‘xepurdenqta 3ut 
/* PUTTANS TOF zequmu AOTOD eA qeTed / {XOTODEUTTANO 3UT 
/s sernqeezy Hbutuy{T3yno seutuzejep ,/ Jeptsepowjogd zeyo 

/* OY weyQ zebzeT Jou ‘stextd ut / Jeztseponqod zeyo 

/« (Z@ 930u 99s) yadep meta uobATod / fyqdeq jut 
/» wobXTod zo eTbueqoex Hbuysotoue ,/ ‘spunog 320°0y 

/= (J @Q0uU ves) Tequmu ZOTOD eA QeTed x/ {ZOTOD AUT 
/» 0dKq uobktod 4/ fedky, 3ut 

/+ wobktod sty z0z sxe zea Auew moy y/ f‘squtoggyozequmn 3uUT 


} 


qeuzogAtog 3onz4s zepedky 


*peutyzep eznqonzys styq sey uobAtod yorg 


- ogut uobAtod uotstaequeg 


/* wotsuedxe y/ ‘ped qut 

/» Sepou eurerq »/ isepon QUT 

/* STextd ut eze squnoure (-+) ‘pezequed st oO «/ SQUTL ‘weg Qut 
/x zeqystbez zed satq p Jewroy - aoux x/ [ze] eqqeTearoOTOD jut 

/» euexy sty ut suobATod zo zequmu ,/ ‘sXToayozequmn Aut 


/* 
“esn O23 punos YOTUM “ASTT xx 
punos eyQ O4UT xepuyt ue st (SsXEJRO TTL) xx 
Jeuueyo styy FoF punos ou T- xx 
punos juezizno AztTpow Z- xx 
Jeuueyo styA st punos dogs ¢- x/ ‘[z])xepurteuueyo qut 


/» ewerzy zed sueemq Jo requmu x/ feqeyqueemy, QUT 

/x pesn jou st zdey ‘zeqjuno> jeedez st [dey +/ ‘zdey ‘Tdey zeyo 
/=x INaamado ‘Exando zoy zequmu euexzy suTequoo »/ f‘uzeg Buot 
/x epoodo eurexzgz y/ fepoodo aut 


/* 


ee 
ae 
»/ 


{ 


} 


qeurojewerzg Aonzqys zopedk3 


‘peutzep eazngonzys styQ sey ouwrezzy yorg 


- oOguT owezz uotstaequeg 


/» woTsuedxe ‘Le]ped aut 

/« 23e ‘peeds zTey st og ‘peeds Teuzou st OCT fetaonzopeeds Aut 
/*+ punorbyoeq e st deurytq ysatz FF OFez-uou /punozbyoeg 3UT 
isdenqtazozequmN AUT 

JspunogyozequmN UT 

/seurezgqyozrequmN ut 

/+ 5utpuedxe zr0oz butpped ‘Loe]ped aut 


90P "INVA 


/* 
ee 
4% 


a/ 
{ 





FORM and Chunk Registry 459 


IFF Specification 


!LATZOTOD 
‘[9gz]ant anxan 
‘0sez SNOT 
fedkq SNOTN 


/x eTIeZ dn yoot e7hq 9gz SUL x/ 

/* NOISNWAXG TUNTNA WOA AAAUASTA »/ 
/» seutyep edXq eaoge seg y/ 

} 

qonzjs zepedxA 

/x sedky [Te FO setTqe_-dn-YooT AoToOD oF ZonzAs syL »/ 


IeFIFFIIIXO SLIG GZAMASTA INIO eutsepe 
/*« peuteto ATTewr0os [TQun pearzesez ere 4 < sedk3 ttw «/ 


/+ S5eTy eatjebey peumssy ue 30 »/ LOASANN_LNIO eutzepH 
/x Bete eqeq peubts e ynoqe MoH «/ 9QESONNN_LNID eutzep# 
/* suotqjeanqes x0F INT ¥ x/ LYS_LATO eutyep# 
/* seny x0F INT WV x/ GAH_LATIO eutzep# 
/* sentq 10F LAT WV x/ GATE_InTo eutyep# 
/* sueezrh zr0F INT ¥ x/ NEMID_LAIO eutzopH# 
/* sper TOF LAT ¥ x/ aza_LATIO eutzeop# 
/» LAT Aqrsuequy zo ysexrquoo ‘euoryoouoW W x/ ONOW LAID euTzeop# 
/* 
“SENTIO 379-8 JO STOARTF WUSETETFTP TOZ soutTyzegd » 
x/ 


(,L,'.0,',T.'.0,)QI@XN LATO AI eutzep# 
/~x MUNYD LAID & TOF OTe GI YuNYyoO AAI SYR ST STON x/ 


2 suotqeotsztoeds 

*zeuueu oTqeonpordez e ut e7ep TeTtUTs TeYyAO 

zo ‘szeqsthex xoToo ‘ony ‘uofqeanjes ‘Aserquoo ‘Aqytsuequt 3tTq-8 

SETQ XO SRZeTSUCTQ OF peEsN OTe SETGEQR SseyL “TeASTIRST TSEReT 
oz QewrosF oTduts e ut seTqeq dn yooT eAep 3ATq-g eTOAS OF 

resodazng 


*zeyqoue 
03 ENTRA 3ATGQ-g eUO TOF uoTReTSUeTA e& se ATQOeATp pesn oq ued 
STAI STYR UT SeTIQUG “seTITRQUe ATqQ-g 9GzZ 4YATM eTqeQ butuTequoD 
eTNpou eqep esodind tetoeds e st (eTqezL dn YOoT TOTOD) INITIO ¥ 
:uotadtzoseq 
*,ZNID, yzUnyYD meu oyQ r0ozZ Quewetddns gqr eyy seqtTzosep oureu sTUL 
UOT QONpoOTAUL 
S3dd TOF YOTMTODOW “A uTasnc Aq 0°Z DA ieTeMAZOS HuTyAz0ddns 
qtesodozg OTTqQng :sn je AS 
YOTWIODOOW “A uTASsNL rwozg 
eset ‘2 Atnc = :e3ed 
etqeL dn xooT 20TOD ATa-8 AMI uDNTOn 
jesodoad yunyo gaI INITIO :FTLIL 


LzSt ebesseu zzt/aep’ ebtue 


yunyo eTqez dnxooqy roTCD 


90P"LNTO WA Tl 


*qxe 3 Butpeey eyQ ut ebueyo eTAyg yore zr0z 
Azque suo ‘seiunjonzyjs eseyq zo Aerze ue Fo systsuod yuNYyS TenqQoe suL 


febueyoosa { 

/* pezoubl x/ ‘ped qaaomMn 

/* pezoubl «/ fZ0TOD «=: ALAGN 

/x pezoubl x/ ‘eTAAsosTW 8 =6aLAEN 

/x 83tq eTAqs ebtuy «/ fetxjas = aLAGN 

/» pexoubl x/ UMNFUOT FLAG 

/» eBueyd Fo uotTzesoT zeYD «/ fuotqeso T q@aomon 
} Qonzqs zepedxQ 


IST UOTQTUTZEep erNQoONIzAAS seyLZ * (buTpeey euTTAno ue ut sebueyo 

etkas eq AtTuo ATQuezins eq ued eTeYyR ‘‘e°T) pesn eze soentea ,eTXkjg, pue 

,UOTABDOT, vyQ ATuo 3eyQ adeoxe ‘(AqtTTqQTAeduIOD oJ) ,aqyoM, edAQ wroz 

JiI 9YQR TOF YUNYO DOSA OUR OF TeOTQUEPT ST ZEewIOF SYL “SeTFTpou 4T 

yunYyo LXIL ey zeqze ATeq,etpeumt azanovo prnoys AI ‘“yUNYO LXaL Zuesez ysow 
eyy worsy butpeey eyq ut sebueyo rzoToo/eTAys/quog ey seath yunyo stuL 


oosd :-dI YNAHOD 


*qx0q Butpeey ey so yQbueT eyQ seatS oezts 
yunYyo eyA - peQeuTWIeQ TION jou st 3x0q ey_ * (Aqdwe gt ueae) yuNYyo 
LXaIL & sey Bbutpeey yoeq “HSutpesy e Jo 4xeq TeNn}_oOe SYA ST YuNYoO sTyL 


“XaL -dI ANOHO 


*(euo ueYyQ ozOU Jou pue) euo Aq 47 eseerTSUT 02 IO 

(oO 7O umutTuTW e YQTM) Qunouwe Aue Aq enTea Auezinod sey eseerDep O23 ZeYATSe 

eze TeaeT BHbutyAseu syA of sehueyo ptteA ‘sehueyo TeaeT HutyAseu eyQ useym 

ATuo yunyo LSaN & epntout 09 Azesseveu st AI ‘“oreZ st (TeAeT AsourTeyNno) 

TeaetT Hutrqsou TetqAtTuT syZ “euTTANo eyA Fo TeseT HutAseu quezizno meu eyy 
seat 3ey3 entTea (eqhq omg) prom e Fo ATuo FO systsuod Yunyo styL 


LS3N :dI YNOHO 


SXNNHO 


“szejooy pue srepeey TOF syuNYoO TeuotyAtppe 

auos pue OOSa eqezodzoouy oq sue{d ere erey, “pesn eze syunyo 

BSN pue LxaL eyq Atuo ATQuezazanDp ‘our ‘ezemgzog suoztTzoy men Aq 
ZosseDoid eept MOTA eYQ JO AewIOZ ehezo js eTTF ey st dwaH WAod 

ruopTqdtzoseq WuOd 


awWaH :dI Wao 


waod 


‘pur ‘ezeMQzOg suOoZTIOH MON - ssoTAeg sourec :Xq peqqtuqns 
L8/€0 :pezAtuqns e7eq 


Dosa ‘LXAL ‘LSIN syuUNYD ‘GWaH WHOA ‘:aI yuNnyo/wuTET 


NOILdIWOsSad MNNHOD / WHOd AAI 
(‘OUI ‘ezeMgzosg suoztz0H MeN - MOT” Aq pesn WHO) GWEH ‘HILIL 


BSIVMAFOG SUCZTIOH MON - MOTT 


290P'0VSH 





Devices 


460 ROM Kernel Reference Manual 


(qbz9) xoToD yore zoz euo ‘spxom jo Aexzzre - TaLO' WATT 


(ggnqs dnqes eTtyz) spzombuct ¢ 
933eTed zojToo otureudp - goxCG’WETI 


(wep otureudp) AI metathtqd rox yo qMeN 


syUNYyoO zOTOS wey oTweutg yoqMeNn 


90P"dOAG 19190 Wal 


“ZATO SATT seuo TTeus 

ueyq zeyqez setTqeqz ebze{T z0z peqtns 20693eq edAQ WO IO YyUNYDO 

zeyjoue esodozd 03 eq prtnom uoTasebins Aq ‘uotssezduoo ejep 

worgy 4TFOUueq PTNom snyy pue ‘seTrque ywy9 eAeY Wed ETGeQ 3ATq-9T e 

3ey3 st Sutuoseez AW ‘seTqey aTq-zeE TO ATG-9T OF UoTsuedxe oF 

epeu st uotstaorzd ou ‘zetnoyzqred url ‘uot Aequeuerduy eqeqTTpoes 
03 (SSIM) eTduys yunyo styq ydex ATeqezeqTTep eaey T 


oo0r9 xAdOd" 


tenon ee ee ew ew —— 
* t0’0'n9 ‘0 ‘o ‘ze 40 ‘0 ‘0 
v9z LATO" 


“s" 49 49 ‘8 ‘0 ‘0 4002 ‘OZE 
oz HWA” 


WETI 78279 WdoOd 


:butddew Aqtsuequy rox yunyoO LnTO eTbuts e yATM 
WHTI ail ue se pezojs efeut gxoozxoze e& xz0zF wesrbetp xoq e st ereH 


“q ueyQ ’5 “Y ‘MOT B UT SINID SezZYQ OAQTIM PTNOM 

nok ‘suot3oezz0p AytTsuequt g5y eX03s 03 SLNTO Hutsn oezem nod FI 

‘wey3 ueemjeq seddkQ4 yunyo zeyjo qnoyZtM wroy e ut rey eboR 
SLNTO TTe dnozh 03 eTqeztsep st 4t ‘eutTeptnh Texzeuebh e sy 


“uotqeuzogut Butyzoddns zey jo 

ou y3t sgnTo AtTuo utequoo eu priod e& ‘zeAemoH ~punoz ATTeurou 

@Te SGYWD SB ,UOTQDSS, SUES ENR UT ‘XUNYSD AGO SYR Er0Feq WAIT 
Wiod ue JO GHWH EY TeAze reedde TTTM yUNYO TNTO eyy ‘ATTEUWION 


:eTdwexg LATO 


90P"LNTIO Wal 





FORM and Chunk Registry 461 


IFF Specification 


SqIW OfTUOTIeSeTA Toy eaTts ueq Aq II 3utedd 


TAWMLIOS SNILWOddAs 


feqeqsdszeg { 
/x» XTTQeUW UOTReIOT »/ ‘ fe] [e]30z oezgbuot 
/* 
sfTxe ,pextz,, Buote uwopjou xo 
‘peuzosized uotqeqor e& ‘pexXOTTO sem uojqnd » 
Ssnou ey SUT ASeT eGR TEeQUeD Ysnirg »/ {zequepiguzed =  yutToan 


qutod esuezezez se 
‘uo 4seT sem ptz6 ueym z9eQUeD Ysnig {zequepzgptz6 =—s_ utoan 
/* 7esey vO seob pth eqQ ezeym {qeseyptzb qutodan 
/* Z'K'X uy buyoeds Sbutpptzb ‘ptzb 3utoan 
/» 7Unouwe Buyddeqs epbue ebzey {deqse Thue Cao 
/* PEXTT St SZeUTPIOCD YOTYM {proogRXTZ craom 


SpI00D TeNAITA UT 
‘deuqtq Bbupyoeq of eaT_QeTOT 
‘eatqoedsied zeques Jo spx00D y/ ‘/zequeDA ‘zeQUeON q@aom 
/* WAdep eatqoedszed ,/ fyqdeq oezabuot 
/x (seezbep ut) sethue uwoqzqej07 ¥/ ‘OF ‘at ‘NT qadom 
/+ 2dXq wot 7eQ0r »/ fedxi 302 @aomM 
} qonzqs zepedky 


/+ 23e98 eaTQOedszeg Bbuyqtrosep pxzopez yxsTC x/ 
TI  UONT_Lou eutzepy 
O UFINA LOU eutzopH 
/x edky,0z etqetzrea Aq uexeQ sontea ,/ 
fqutodn { 
fe qutoay 
T qutToddt 
} uofun zepedsy 
SLe]autoay oexzgbuor zepedéa 


fqutoagat ( /z/A’x oezgbuoy ) qonzqs zyepedAA 
fpezgbuolT SNOT zeopedka 


CA.‘ sds‘ sds’ 0s) CIOXEW Addd GI eutzep# 
/*s Add@d TOFFTIUSPF YuNYS ouL »/ 


:0edg yunyo 
“WHTI I1QUTedd & UT eReQs eAT ZOedSIed eYQ seqTIOsSep yUNYSD Addd SUL 
ruoyqdtzoseq yuNnYD 
BATTS ued :kq peqatuqns 
98/2T  :peaqtuqns e3eq 
(yunyo eatqoedszed WHTI II 3utedd) Adda xunYD [aI yunyO/urog 
NOILdIWOSad ANAHD / WHOT AAI 
(wa) yunyo eatqoedszed qutedad 


90P"AddQG Wal 


K tdp x tdp ezts Iad 
DZTO 0400 YOO00000 OZ6F0ShY 


rs® peaes oq prtnom tdpoog Jo uotqntosez TeoTAzeA pue Tdpoyz 
JO woTAnToOsez TeQuoztTzoy Ae pouueos eheut ue ‘eTdurexe r0g 


* zepeeHIdad { 

:K_tdp agomn 

ix tdp qaomn 
} qonzqs zyepedx 


qe pouueds sem 4T uoTANTOSeZ oues 
eyy ye ebeur ue Fo Andyno motte 03 your req s30q = Idd’ WaTI 


06-9T-T 
ANWISNG 


sade stas wopuoT 
peeqsumtd 


Puy eqseueD 9T 
uosueys xzeoueds 
:Aq pezeqstbeoy 


yunyS Idd Wall 


yunyo yout zed s30q 


90P Idd Wall 





vices 


: De 


462 ROM Kernel Reference Manual 


/* [199 zeqsy~bex ToTOD ¥/ ‘xepura { /xeput gLAGN /TTS> aLAGN } 3OnzAs FepedéR 
/* TT®2 ZoTOD enzQ x/ ‘zoTODd { /‘q‘b‘x gLAGN ‘/TTSO aLAdN } WNTAS yzoepedx 


febueya { 
/* MOTTOF 03 SZONTAS xepuIg Jo requmu ‘sBexza gLxAGa 
/*x MOTTOF OF sjONIAS zoToOd 0 zequnu fenzqu FLAGA 
/* Ganaasaa ad ON=) 'FATLOW ON=T isbetz LYOHS 
/x puones/sdejs 09 = peEgT ‘eqez ButToAD xzoToOo {e3ez LUOHS 
f/x ONTeA TTS. xe ixeuw FLAGO 
/* SNTeA TTS uTtuU futw gLxzAan 
} qonzQs werecks 


sbetsy agzawasau ad Tome eu 


*ebuex 
ey3 eTOAD LON pTnoys wezhord eyy Aes LON ST 3TQ 92 FI ‘eouezezezd 
weabord/zesn & ST AATLOW SONA wSsyR Aout ere suoTATpuos eaoge ey3 FI 
zeqstbex roOTOD 10/pue TOTOD euo ueYyA erou sey <E 
eqezr peuTzep e sey <zZ 
zejstbexr TOTOD euo AseeT We suUTeQUOD <T 
137 JT HALLOW Ona eyQ eaey ATuO ptnoys 
ebuexz vw ‘etqetodd st ebuez ey3 ueym jes st sheTy BALLOW ONY SUL 


ebuexz ey utyatm szeedde zeqsthez XO ZOTOOD ey ETEYM ST <TTED> e 
{ »xXepurld xzoTOod ebueud } # .DNUd. =:: ONG 


xunyS ONUC AIQUTedd -suoTReWrTOZUL AIT 


90P ONY WaT 


seToko HSutyDoTzequT of (30K) ueath ueeq sey qyHnoyQ ou » 
“yunyo OMId & 4NO EARS TTTM AT SSTMTEYRIO TEpow ONYD euQ 
sqtz ebuez ey3 ST ONYUD ebuez eTAAs pTo ue Ano eaeS TIT QuTedd * 
TOQON 


0=3 03906 

{z] ‘ebuez0 {tl 
‘entq {t] 
‘{z]tedzno = [(T] 
‘ueez6 {t] 

‘moTTok = [1] 

{z] ‘{t]tedzno = [Tt] 


[moTTe4] [ueez6] [z] [entq] [eSuez0] [1] 
LeATT YOoT ueo ehuexz znoz 
:etTduexe 10% 
“BbutToAD zoToo TeuoTaTpezy yqtm Bbutrpoko qbaz eutquos ued nox » 


ueer6 
MOTTOA 
[tT] Tedzno 
eSuexz0 
entq 

(z] Tedzno 


SCHANMNTHOYO 
Hud it th ttt 
bv HY 


0=2 0306 
efuezo {tl 
entq (t] 
etdind {tl 
[t]Tedzno = [T] :eT 


‘eTokd ayQ ut rOTOD yxeU 
ey 3 Uo SYeQ TITM T r9eqstTbexz roTOD yOTR eToAD yoee Qe ueyR 
{etdand] [entq] [ebuez0] [T] :exTT syooyT ebuexz aznoA FI 
:etdurexe xz0g 
*senTea qbz so setzes e nzyq zeystbez eTbuts e eToAD mou ued NOK » 


dueq = [T] 
‘(t] Ce] 
‘fel (81 
‘Te] [2] 
‘[z] = dueq 
YOTQ eToAD yore Ae ueyq 
[zl(slle]{t] ext syoot ebuexz znoX Zr 
:etduexe 1035 


*szeqstbez 
zojToo zo ehuez snondyTquop e utequop seToAD xroToo yey extnbexz 
LON seop yoy Tepou butToko are meu e& sqizoddns arauread * 


setartrqedeo But toh Z6T05 areca! 
:esodang 
uezey eet Aq peqqtuqns 


WATI Wdod TOF HUNYD SNAG 


(wa) yunyo eToAD xoTOD peoueyue AI 3uTedd 


90p SONYA Wal 





FORM and Chunk Registry 463 


IFF Specification 


-Kexze ey Fo satwryt BbutTeos eyA eath of YUNG AMYW O4Q UT pesn ST NIWA ‘“eZTS 
STQETIEA SEY YuUNYD sty os ‘QueqAsuoD eyR Jo eZTs eqQ suTequOD edAjeQep oUL 
-edky 3eqQ FO QuUeQsUOCD e ueyQA pue ‘edAjeqep e suTequoD enTea eyL NIWA 


{ »(axXialouis|xAwaw [wowd]) sata }# .adas. =:: oaLs 


‘este Butyq3Azene 

SXATT woTAyUTZEp peqseu e oeney Aeu prety yoeo ‘uyeby ‘ermnqonz4s eyQ UT 
PTeTF yore Fo suoTpatuyzep eze Atqasey -“eanqonzAs eYR UT SsPTEeTF FO 
zequmu ey3 seat& yotym ‘SaTA St OULS & UT yUNYO (pertnbez) Asztz euUL 
-sbuty 3 IeTTUTSstTp FO ASTT pequNOS e seUTyep yunyoO sxzngQonzAs suL :NULS 


{ axial nuns|xmaw [yova] [adda] [amot] wara }# w.AWaW. =:: ARMIN 


‘este ButyqAzeae eYTT UoTATUTJEp peqseu 

e oq Aew yotyam ‘Aerze oy FO Quouweyte ue Jo woTytTuTzep eyQ st ATAseT 
“eqep ey so Buytdwes BHutanp Butrteos ut pesn eq prnoos yotym / (Yddn pue 
UMOT) ‘ueatd sqtutt eq Aew ezeyq ‘Atteuotado ‘Aerze ey ut squeuwets jo 
zequmu ey3 seatTh yoTym ‘NATE St AMIN Ue UT XUNYSD (pertnbex) Asaztz euL 
“suieqtT Ze[TWTs FO ASTT pequnosD e seutyep yunyo Aexrze ey, :AMIW 


Aqog 
(azzaq | awas | AMIN) woTZTUTJEep 
XaLW Wed 


“ESIT © UT (sxdog) s3es8 Zep peqjewros ATTeEoTQUepT yRTM ‘AyreGoud & se 
UOTATUTFJOp S43 SsNn PTNoo peer Far TeqTeus e 4ynq ‘eAeEp Fo yes euo ATuUO st 
ezey3 ‘ATTeEnsn ‘peutyep st YOTYM Rep eyQ suTequoD yoTyM xGoE Sua Aq 
POEMOTTOZ ‘emn_ONIAS ay FO uoTITUTFEp ey Fo pesoduod st WYOT KULW SUL 


SMNNHO 


*zeq30603 s3Tq eyy Bburssezduos pue ‘sqtq reMeZy YITM Tequmu yore Huy queserdex 
ZozZ wuopstaocad st ezeyR ‘eTQerTsep ueAzZo sT UOTIZeAXeSUOD eoeds sDUTS 


‘sKkezze zo Aezze ue Atdwts 
st Aexrze [euotsueutp-omyA Ww “srequmu OMA suUTeQUOD eANQONIAAS YyoRS eTeYmM 
‘seangonizjs zo Aezze ue se pepooue eq prtnoo sated eqjep so jAsTT e ‘eTdurexe z0¥g 


‘yadep peztsep Aue 03 peqeodez eq Aeu sexrnjonz3s BHuyyseu jo 

qdesuo> styz ‘“TTem se skezze pue serngjonzys zeqj0 utTequoo Aew AoyQ 

- e3ep oTU0Ae septseq sbuty3 Fo pesoduocs eq Aew sexngonzys pue sXerze yRog 
‘quezezztTp exe yorym shutyy FO seqstT exe yotym ‘sezngonzys ‘ATpaTUL 

‘eures oy3 TTe eze yotym shutyy Fo sastT Atduys eze yotys ‘skerzze ‘ATpuooes 
*zequnu jutod SuyjeoTsy zo ‘zefequyt ue se yons ‘eqep oqpuoje ey ‘ATQSATA 
*sbutyq yo sedXk3 eezqy Jo pesoduod st ‘uoTATuTzep ano Aq ‘x}TxrQeEU W 


“SeTTS JaI XULW 4ndqno 

pue setts FTose peez oj werhord euo 3ynq eq O73 speeu ezeyL “STTF e3ep e& 

JO szejeuezed eq ssenb 03 peeu zehuoT ou suexborzd 3eyQ Yyons ‘jeuTOF 

S83} eqTzosep ATejeTduoD pue ‘eAep eyy EeT0Rs YAO" TTT WAHOd XUN SUL 
‘eTqeqzod jou st eqep ‘yons sy ‘“sezts pue ‘sqtwtT ‘uotssezduoo ‘Sut qyewroz 
‘suofsueutp FO Tequmu eyA se yons ‘eQep ey Anoqe peuMsse st Yonu ueqzo 
*qseeq pezeuueU-[TT ue st ‘PTIOM Teer ey WoTF sevlOd QT se ‘eQeEp TeOTISUMN 


> NOILONGOULNI 
(2Qe ‘ssezppe) 
eTeMAzFOS sees UeAeS 
yonog Bnog :Aq pey zyuqns 
o66t-Atnrc-6t ebezoqs ejep xtrzew TOF ‘WAUOA XULW 


(seeg ueses - UOTSTAUReN) eber04s eqep TeoTITOUMN 


90P"XYLIN 


eTTF adzxzosqsod tTTose : (] wyHo 
‘Kayq5yrzzeddn aiom 
éxqybyazeddn qiom 
JAQZOTIOMCT TYOM 
!XQJOTIOMOCT CAOM 
xoq butpunog ‘ 
yqbuel asag 


‘ebewy otydex5 s ,WaTI ey JO uoTAequeserzdex 
adtzos3sod e sptoy ‘32e dtto zteyq ut adtzostexta Aq pesn 


adtzosysod peqetnsdesue ptoy o3 yuNYD 


PIPG-LLZ-LT9 - WeUZATES UTASY sUOTIETOXTA 


yunyo isda Wal 


yunyo ydfzosqsog peqetnsdeoug 


90P"4Sd3 WAT! 





vices 


De 


464 ROM Kernel Reference Manual 


JO exou TO eUO sueCMT 

HuymoTToF ATun eqQA Fo ezts eyA sueow # 
; Teuotqdo sueeu [] 
nACOEn AGOG 
uWOWdn 
wSCTin 
udALdu 


eqeq dump Azeutq ysxztsz-xzeuut } 

buyyoea queuubyTe 934q pq pexoed satun } 

spTetad FO zequaN spTetzy JO zequna } 
dXap } 
(zetTeos) edky eqedq sseTo ‘ssetoqns ‘ezts } 
(wofzun ut) eNnTeA entea d&ap } 
AUTT uMUTxeW OTWA } waddan 
VFUFT UU UTW OTWA }) wAMOT. 
squewete Aezzy squewetTe }# .WaTa. 
eznzonz3s «(dkaalouns | xAMIW (wowd]) sata }# .OdLSn 
Aexzzw { azznalours) xray (uova] [udan] [umot] wata }# wAwaW. 
AGOW dxALA|OULS|AMIW uXBIW. }# wAAOT 


XFIIEW { 


* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 


‘eTdurexe zoz ‘sxequmu jutog SutAeotTg peqeounz3 pue ‘szefequyt ezts Arezqyqze 
qxoddns 03 se os ‘Ajeqezedes eztg pue sseToqns ‘sseTD ey AepysuoD TTA 
szepeez pejzeotastydos ‘edXjeqep enbtun e seutyep ezts AUueTezssTp yoro 

QeqQ soumsse yotym ‘sedAq umouy Jo yes TTeus e yaTm edAQeRep eToym eqz 
exeduoco Atduts ued zepeez eayeu e ‘odAjeQeEp uteqzeD e rox Huyyoeyo ur 
“szepeez peqeotastydos pue eateu xox BHbutmoTTe sem Teoh ubtsep p2ztyy wv 


*queweje4s YyoQTMs 5 e ut peztutado eq Aew pue ‘sofotput Aerzze se 
etqeatns eze XAoyq ‘peubtsse AtTeTquenbes eze szequnu eyQ eDUTS ~“sPTETF 
eq Sbupsseooe ueym BGutqztys pfoae of se os ‘erngonzys e se edXjeWep eyy 

Bututzepez so uwotydo ey3 eaey nod ‘sejkq uo sptets Butubrte Aq -ezemazos Aq 
pepovep ATtsee sft yoTYM ZeUTOZ e eQeETD OR sem Teoh ubtsep puocoes 


90P'XY¥LW 


“seyseToO Queaeid oj ezopoumoD 

Y3tM 3 reqstTbez oj peeu TTT nok ‘ssetToqns Xo sseTD enbtun AtnzQ4 e& 
eaey nok JI ‘“seTnz eseyy HutmotTos Aq setatnhyque ro seyseto edAq Aue 
eq 30U TTTM ezeyqQ 4nq ‘edXq mou znok jzoddns Aew szepeez XYIN TT® OU 
qeqq ezeme.og ‘sseto Axeutg peubts ey3 ut satq rnoz se ezts ey Bbutath 
Kq petyyoeds eq wes zebequt 3Tq-y © ‘eTdwexe zoq ‘sedkz ejep butqstxe 
wo suotqetzea ezts Atduys eze sedky eqep Aue ‘oqut Sntd ATtsee ueo 
etdoed zey30 yotyM weqsds uoTQeDTFTSsSeTO © eReETO OR sem TeEOb ubtsep ¥ 


zeqoereyo 


! 
eTaqtn 


pepped ooveds ‘yQhueT pexta 

e3Mq 4srtzy UT sreQOeTeYD Fo zequmN 
3x03 pe qeutuTez-TION 

qutog ButzeoTa 3seq eTOTOIOW 


uoftstoerg eTqnog peyeounzL 
uofstoerg eTqnog 


uotstoezg eTbuts eeer 
Buorn 


PIOM 
oa 0 --- peubts Azeuta 


Su071Tn 


ss=== 


sseToqns 8SETO 


edky ofztoeds Teutgy ezts 


“moTeq eznqonzy4s eez3 eYyR UT ueaThb 

st sedXk3ej3ep so uotstatp ofseq ey, ‘“setdnovo eqep ey woor yonu moy ZeqM 
STTS3 ezts eq ‘ATTeuta ‘pesn Hutpooue oTzToeds eqQ seath yotym ‘ssetoqns 

© ST SSETSD YORO UTYRTM “99e pue TeuToeq pepop Axeuta woxzz szequma qutod 
ButzeoTs worzy szebe uy Hbuyyeredes ‘uofRouTAstTp xzofeu Asou syQ sexXew sseTD SUL 
‘ssetoqns (¢ pue ‘sseTD ey3 (Z ‘s3Tq Uy EZTSs EY4Q (T ‘SPTSETF SOTA OQUT UMOp 
uexyorq ere S3Tq ZE SUL "S3TqQ ZE Y3TM e3ep OTTeumu Jo edAR. eTqeateouCD Azeso 
suTzep of sydueqqe Af se ‘yunYo HuypAsezequT ysou eyQ st eddépejed eyL * dia 


*“KiTeranqeu eqfq e uo subtTe yoTYM Tequmu WoOvd YeceTTeus ey y 

St g O8eD STYQ UI "YZ = Bx OUTS g Eq PTROYS NOVA ‘szequmu 3Tq-¢ jo Aerzze 
ebzet e Suyyoed ueys ‘etduexe zoq ‘“peztTeuzou eq prnoys rzeTsyoeds ywowd euL 
*uotaTuTzep yxeu eyQ butssesord exzoszeq ubtTe-e7Xq of suReU O JO HOWd VW 
‘eaoge suoTATUTsZep ut sYovd Aq peqoezsze Jou st ay - 3INezep Aq T FO Mowd & 
eaey OF poumsse st AWE TO NUS WY ‘“YoOT_eOTZTOeds meu e Aq ueppTzzeA0 
T¥qun xo ‘edoos peqseu sqt JO TSepuyeuer eyA TOF QoOeFZe UT st WOVd W 

*eqMq e uo ButubstTe exozeq yoered-3tq 03 sueqtT Fo Tequmu ey y - TequmuU 

e Atdwts st wowa ‘“zeyQe6oyj sueyyt ejep Bbutyoed Aq eveds eazesuon oF 
seystM zesn eyR pue ‘peubtTe-e7hq jou ‘st jeyQ ‘g Fo ETdMTATNU e QouU 

sft e3ep oyQ Fo YRHueT 3Tq eYyQ ueYyM Aresseveu st YuNYS WOWd SUL >wONd 


*peubtTe-234q aq 03 poumsse st ejeq ‘“Azoueul ut QeuToZ QueTOTFJO-CMT 
exzou e uT er04s Xo butTrzepz0-e7hq ysn{pe of speeu xepeez eyQ sseTun 
‘ysTp wory YUNYO eToym eyQ peer-yooTq ATduys of QueTOTF;NS eq pTRoys 

3t ‘seseo qsou ul ‘“zZeY_O yore Of AxeU peTORS ere uoTAdTIDsSep peyseu 
SYR FO WoORRI0g EYR 3e suEQT ‘st WeYQ ‘QeUWTOZ ,ASITJ-MOT, UF peroys SF II 
*eqTioOsep 03 4OFFS youu os oF QUEM OM BYEp TeNq_oe OYA ST STYL -AGOT 


90P"XYLIN 





FORM and Chunk Registry 465 


IFF Specification 


doq 03 3p - doq wozy yoerqs Jo dump 
xy doqz ey3 zo dump e st 
qzed sty ‘xg ueyQ zebzeT posn yoeQs FT 


do3 03 Quezazno wozz yoreQs Fo dump 

@eZTS UT SSeT ZO 

38 ST pedump eq oj yoeQs Te_I0R JT pesn ATuUo 
yoeqs eTOUM 


yoegs uo spzombuolt so zequmu 
ysezo FO euytyA Qe reqQuTOd yoeQs 
yoeqs Fo doq so ssezppe 


ueqTyxDe AS 
z344oe3S 
dozyoeras 


*seqeuTMIeR SUTQNOI Zesn 

ey rFeqQze peqeTNoTes ‘yunyo ezLyazesn eyA so yabueT 
“(NOT & se eos 09 squem sodebyuy yoTYM) eTpueY 
eTTZ soaebhtuy ue ‘zejeuezed suo exeQ Asnu pue 
spToa, edkQA Fo eq Asnu outqnoz znok ‘spzom reYyQO UI 


idz Bbuot 
(dz) <euweu uwofqouny> ptoa 


r@UTFANOT NYNONO eYR A0z Deds “eTTT 

yoysdeus ey} 07 requtod eTTs soaebtuy ue - yxoeQs 

ey A wo reqeuezed ouo Bbutssed ‘ettz Joyusdeusg eqQ 

butsoTD 03 zozad eutTqnozr sty3 ITS TIM zeyoQeD 

2u2 ‘.MANONO .. TeqeT S49 03 zeQquTod uofTjounZ e 
subf{sse zesn ey3 JI “yUNYO eLya xzesn Teuotado - 


aLwdan 


“4g UeqR SsseT eq GASN YAOeAs FO Qunouwe eyA AeyQ Asnf ‘yYOReQS erTQUe 
ey3 dump 03 ezts ut xg WEY sseT 90q AsnU YORQS OYA URS LON seop 
STULL “eQep yoeQgs Fo yg FO umuTxeu e dump TTTM eM ‘spIOM TETRO UT 


XY + QueTIND 03 QueTAIND wory yore As Jo dump - 
%y wozjoq eyQ Fo dump e st 
qzed sty3 ‘yg ueqQ zehzeT pesen yoOe AS FT 

€ enTea - 


90p’g 19d 


yoe3as 


AP Wo3308 


:buyMo[TTos ey 

zo Aue eq ued yotym ‘pretTsqns yoeqs yo edXq sTTeQ 
spzombuoT ut pretsqns sJo yabuet 

Ptetzqns dump yoeqs 


(aLsa) spzombuot ut pexoed wezhozd Bbutytzm Fo eureu 
weafozd SutAtzm Fo oeureu so yQbuet 

wezfozd But34tzm FO TeaeT UoTstaex AOUTU 

wezbozd BbutAtim FO uotszeA uteuU 

spzomBuot ut pretzsqns Fo yybuet 

SITS SstyA peqeezo yotym wexzhord so uoptsetaez 


szeqstbez ssezppe jo dump 
szejstbez eqep so dump 

zeqstTbey epop uotatpuop so Adoo 
ysezo FO euTRZ We Od 

spzomBuot ut ptetsqns Fo yybuet 
ptetzsqns dump z0e3stbez 


(squeubes ey FO sezts 

yata peated ‘szequtod jst thes TTe sepntour) 
wezbozd zoz 3sttbes zo Kdoo 
wezbord z0z squeubes Jo xrequmu 
ysez> FO zequmu uotTydesxe 
yousgyzomM = oreZ ‘TTD = ozez-uou 
OSIN 20 T¥d sem ouTYoORU 
ZayYASCYM suTUZeQep Of pesn eq Aeu spTetzy eaoge 
esegooxg worz prety AouenbezgAtddngzemog zo Kdoo 
asegoexg worz prety Aouenbezyqyuetga Fo Adoo 
dyyo yeu 
Jo eoueqstxe pue ‘zrosseno0ad zo edkq seath 
‘esegoexg worsy prtets sbetauyaw zo Adoo 
spzombuot ut pexoed oureu wesrboird 
(aLsa) spzomBuot ut euweu wesbozd zo yybuet 
PTetTzFqns Fo yybueT pzombuot 
ysero FO outy We Queuuorztaue Hbutath ptetzqns 


yunyo Fo yqbueT rox pzrombuotT 
xeTZTQUePT yUNYo 


(ed&4) 
yabuet 
sMMLS » 


ouendL 

ue TOUeENGL 
uotstTaer 
uUOoTSsI3sA 
yqbuet 
sSUGA, 


dumay 
dumaa 
sbeta 
<ppwnans 
yabuet 
sSOma, 


astiIbes 
qunoobes 
umNndndS 
ze qze 4s 


bezgdnszemog 
bezaqxXuertada 


quewu0zTaug 
oueN 
ue'JoueNn 
yqbuet 
sTIWd 


yqbuet 
/AL9d, 


"yoegeoezy wer5ozq Buyueeu ‘giod peweu eq 03 ‘edAQ yuNYo wal MON 
:ptesodoza 


2 qeur0g 


aL5d Waod 


(@4ngTasuI sys) yoOeqeoer3 wezborzg 


90p"g15d 





vices 


: De 


466 ROM Kernel Reference Manual 


“squno> 3atq ZL 3nq Sutyaiue buypeez 
qzoddns 3,uptp Aeq, ‘ueqQTrm ezem pzqqStT pue eutheur ueya pue 
‘qunom qeedex atq L & ueYR eTOW UeRQTIM reAeU seq esTnduT 3ng 


un’ AGOG NASA SYR UF se 
Kidde setnz owes eyQ ‘LzZT weyy zejeezH st junoo qeedez ey3 JI. 


seutT BSupMorlrros 
243 pezeedde ezeq3 ‘3ueums0p sty3 Jo uotszea snozaerd e UL 


*qunop qeedez 3fq L & weYqQ pue ‘QxeuU QATq 
nyDoTUeh, eq ‘suofqtsod asW S43 UT SITq ASU HZ SUF TATA 
2UOQITIM ST (SATqQ ZE) PTOM-ONOT S ‘ONTEA AY yore Tog 


:yunyo Apoq gasu eu r0g 


*peqroddns jou 

ere 9EGg9 weYR TeQeezH squnoo yeedey “sMoTTOS 3uN0D Weeder 
GoM & pue ‘ozez st qunoD gqLxa EUR ‘SGz BeYZ Teqeer5 st 
quno> jeedez ey JI =‘SMOTTOF QuUNOD Aeedezr aLAG B pue ‘or0ez 
St QUNOD 3Tq-¢ 9qQ ’z_ UeYR reQeEerH st QunoD yeedez eYyA JI 
‘qunos jeedez 3Tq ¢€ e& ueqQ pue /qxeu QATq ,yooTUES, eqy 
isuopatsod (atq queotTytubts Asouw) asW eUR UT S3tq GSU ZT 
©U3 YIFM :Ueq{ITIM SF (SQTq-9T) GHOM & ‘eNnTes qou yore Tog 


:yunyqo AGOd NASU eq} 10g 


*qunoo qeedez ey go epnaqtubeuw eyQ uo 
BHurppuedep sqewz0z jUeZeZFTP UT USEARTIM ETE seONTeA eyL “WuNOD Weeder 
e sey sXearte entea goy yore ‘syunyo Apoq gad pue NEY 4IOq 1z0g 


“ysnzq ey 

yo qzed jou exe yeqQ stextd syzew 3tq yOoTued eyQ ysnzq e se 
PSEPECT ST SOTTF CYR FT pue ‘(peeqsuT posn sft XOTOO qoy Sy} pue) 
erngoyd © se pepeoT St STTS ey FF perouby st aTq yooTueb eqy 
‘(swexfozd quted 34q yz 3 ZT_esTndmr) pzqubtT pue puowetq ur 
-qbnozyq3 Moys 03 CEepta yooTueh zoz seueTdytq ey A ojUT weqQTaMm 

ST ,TOTOD ozez, e& ‘3es8 ST 3TqQ ,AOoTUeh, weym ‘TeEATTS wl “syjunod 
qeedez pue ‘37q ,yOoTUEb, e ‘senTeaA goY suTeQUOD yuUNYoS AGOG SUL 


“senTea qu 31d oz 
sesn Saou WAOd ©4Q pue ‘sONTeA qu 3Fq ZT sesn NEU WAOT SUL 


‘py se edkq uopssezdmop ey3 pue ‘gaou edXkq x03 gz pue 
Nasu eddy xox ET se seueTdatq Jo zequmu ey sefzoeds yunYoS CHWH SUL 


‘aqmuIndma sI yunyo ONVO W 
“yUnYS CHWE eG} UT seoUeZeZZTP AUSTTS pue 


yunyo xGo@ ey} TOF Adeoxe s,WATI WHOA OF TEOTQUEPT JsouTe ere Aous 
‘euTpbewl pue reaTTS oqany, s,esTndwy uy pesn ere seTTF sau pue NEY 


sasu Wiod pue NESY Wuod 


(estnduz) zeaTts oqiny ‘suzoz ebewt aou . 


90Pp’s8aDY-NEOY 


feqeqseaon { 
/« UT esee OF seuTerZ FO TequmuU futeseo LYUOHS 
/* NO esee OR soueIzZ JO TequmuU {qnoesee LYOHS 
/* 2a0u 03 seuery FO Tequnu /souezzu LYOHS 
/« setbue uopqeqor 2‘A'x ‘[e]etbue rTuoHS 
/» yeweceTdstp eoueqstp z/A‘x -[e]eoueqstp LYOHS 
= /x SAX = T ‘ON = 0 foyToAD ALA 
/» FALLWTRS_HSOUG = T ‘SALLWTaa_Nawos 0 fedAyuotzeTsuezy FLAG 
/* UIGVITA HSOUA = T ‘TALLWIRY NaTIOS = 0 fedAyuoz3zeq0r FLA 
/*x GawMaowd = Z ‘TIILS = T ‘aawmMiod = 0 {xtapzovez FLAG 
/x tod 03 = T  yutod worx = 0 iz}qeaow FLAT 
/* 0 OF SZTTETITUT ‘peazesez FLAG 
} qonzQs 


eqeqseaom } # .ZAOWn 
{ HAOW .duSdu} # wWHOd. = 
suotqeuzosul Jail 
uezez, eet Aq pez gtuqns 


) wzogz eaou eatTQvedszed AI QuTedd 


90P"dSud 





FORM and Chunk Registry 467 


IFF Specification 


“syunyo »AGOdn 
pue ‘, GWYN. ‘.YCHN. S43 UT eze QeuTOZ ,XAS8, SYR worz sebueyS rzofeu oyL 


‘oureu pue ‘uotqdtzos 

-ep edotTeaue umo sat eaeYy 03 SAeM YORe AOZ Azessooeu st 4t ‘(3TY umAp ezeus 
e eq qybtu zeyjoue pue ‘ouetd e uo 5 eTpptu eq jyhtu evaem euo) eTTF punos 
eY3 UT seaemM TeYRO eYQ UeYW AQUeZeZZTpP ATe_eTduUIOD eq UBD eAeM YORS eDUTS 


otsTda 
oWWLYn 


reze Aey, “xunYO AGO. SYR O3UT peqer 
-odzosut ueeq eaey AeyR se 4stxe reHuct ou syunyo ..XAS8. OM ‘SezrOULTEYRQINgG 


*seqhq FO xequmu uene ue oF Ano pepped eq ysnu AvyQ ‘zeedde op AeyR 51 
“@eTTZ punos e ut eq 03 pertnberz exe syuNyD eseyR FO euoU ‘WTOJ .XASB. eu 
SXTI “sosn ATSYQ pue syuNyo oseyA FO uoTAdtrosep e TOF AeYR OF TezeX oseeTd 
‘queumoop ,.XAS8, TeuTStzo eyA ut peqtTzosep [Te ere setTjzzedozd eseyQ souUTS 


wONNWn 
wHLOAWn 
n (@)a 


2 SMOTTOF 
se oze pebueyoun utewez 3eYyQ3 sxuUNYS sy, “weyQ eaorduT of peou e 4,UseM eTeYQ 
souts oues eyq ATqoexe ere syUNYD eyQ FO sulog “sZUNYSD OAUT SeTTF punos ey Fo 

SUOTIOSS sNOTTeA sYyW eAeredes 073 sSTEepReosYy sosn QeWIOS MOU STUQ ‘,XASS, PATT 


wXASBu 


*,2AeM, EB TTPO om Qeym dn oyeu qeyq squtod otdures Aueuw go uotqoeTT[OoD 
e sueou at Attensn ‘otdures e qnoqe sxTeR SOANZeTSATT IGIW USM :SOLLNYWWaS 


*suotqeot Tdde etdurexe yRTM ‘@eTQETTBAR ST SOTTF ANWS OQTIM pue peer OQ suUOCTQ 
-oungy go Azexqtt e ‘osty “Atquresse pue 5 yROq UT pepntToUT use©eq eveYy QeUTOT 
STYA FO Osn oY SReTASUOUSP 03 soTduexe SHutumrezbozd ‘,xASE, wWeyR xeTduos ezouw 
ST QeUTOF sTyQ esnedseg ‘soueUTOZIEed Fo TeAeT STYR eAETYOS OF eTGe eq snyy 
pue ‘Suttdues 31tq 9T Quoeuertdwt TTT sTepow ebtuy ezngnz yeyy uotqedtotTque 

ut ‘szetdures otsnu Teuotssezozrd Auew uo punoz sernqeez eQezodzoout 03 sqdueq 
-38 3T ‘uotatppe ur ‘szetdues [Teotsnu ‘peznqoesnuew Atquezazno {Te AtTenqata 
seop se ,squeae punos, Sutqtzosep Jo poyjeu (eoezzequr TeqtTh6tq yueumzysur 
TeotsnnN) IGIN ey 3 Uo seTTeT yewx0Z styR ‘Huttduwes Teotsnu uo st stseydue 

243 esneseg ‘but tdues [eotsnu oj spzehber ut wI0F .XASB, SYR JO seToOUeTOTJEp 
Kuew oy 30087705 03 pepuequt Attzeutad st at ‘(yoatd jes e je peXetTd spunos 
qoyseuo AtteotdéR) ,,sqoeFFO punos,, eT0R4s 073 pesn oq Ued wIOZ stTyQ YHnouALTy 


*(Teuueyo zeyjoue HutAzernpou st yoTYM Teuueyo otpne ue 03 Aues aq 3qbtu yeyR 
eqep etdures eyQ ‘etdurexe z0z) osut ofstoeds ebtwy ezojs 03 Agtrtqe euyy Bbutyex 
-odzoout oste eTtTym /’(ebez0oqs etdues Teotsnu roxy pzepuegjs ojoesep ey A) prep 
-ueqs dump etdues IdIW eU3 JuUNODDe oQUT seXeQ ZeuTOZ stTyR ‘ezouzeyqIng “wroyz 
-28AeM YyoRe OZ poeuturejep ATquepuedeput eze (,Aetd, TTT wroyzenem yore se jou 
Teotsnu yotyam) Hbutddeu yoeqhetd pue (ezts wrozeaem) sy buetT eyR ‘QDeF UI “Z 
JO SIOQOeF Oq OF SAPY YOU Op suUTOJEAeM QUeTEeZZTP JO syQbueT eyQ pue ‘eAeQDO 
zed wzozeaem euo ueyQ ezouw eq ued ezeyL “eqep eTdures ATq g 03 peRoTrAser 

you st qeuzoz meu sTyR ‘,XAS8. OATTUN “.XASB. ‘PTepueqs quero oyA exTT shew 
eUOS UT BAep punos poeTdures 9103s 073 pesN WEUIOF STTF & ST ,aNWS, WIOF oy 


squeptsstp ‘33eTD syer pue eroTZ wc = sword 
686T’€ DPQ =: eRe 


punos petdues ,dwys. WHOd JaI 


qeuzoz punos petdues 


90P'dINVS 


‘or9zZ TOTOD rozZ yoeTQ anq HutyyAkue yazoddns 
LON seop zeaTts ‘(gg des) buyqtTxzM styz Jo sy :eqou TeTDeds 


‘s,€ST ey3 se sqtq entTq eyQ pue ‘qxeu sqtq 

ueer6 ey3 ‘S,gSW 93 SB S{Tq pez sYyA YATM peo js ere seNnTeA 
au (3TQ pz ZO ZT) EYL “wWoRR0q 03 doq wozz Hbutssesozd ‘seutt 
Tequoztzoy ssozoe AyHTz 03 AZEeT worzzy pouueos ere stTextd eyL 


{ 
‘(eTtaa5u) 305 (qaomn) = 3uno0D 
(((@TtaaDu) 2305 (aLAGN) = QuNeD)j) FT 
(qunodj) 3T 
{ 
{L394 = unos 
iy << m = qbz 
‘8 9 M = YDOT 
‘(eTTaaDu) ™9e5 (qgoma) = ™ 
} este { 
‘3L000000%0 3 4 = AuNOD 
!g << wa = qbz 
4080000000 3 4 = YOOT 
i(@TTadoOU ‘T ‘bp ‘M3) peers 
} (gqba) 3T 
} (qunedi) st 


tepoo xdo@ eTdures 


90P’8gDY-Nd DY 





vices 


: De 


468 ROM Kernel Reference Manual. 


/» SXequMuU eAEM s,TEUUeYS E€ TEYIO eYR YATM Sues oY4Q OP x/ 


/+ (@powkeTd LNWONAGAGNI JT) O# Teuueyo ofpne ebtuy uo enem 
styq Aetd pue ‘eotaep otpne sy3 03 pessed eq of peosu 7eYQ 
SONTEA SYA CUTWTEQEp ‘’eQIeEp s,TH# EAEM OF TEQUTOd eY4Q 30 x/ } 
(0 =i UnNeAeMQUeYDS) ZT 


‘Le+aqeszzodey] deyketd (gixan) 
‘(z+ 3eszz0dey] deyketd (azxan) 
‘[t+3°szz0dey] dewhetd (azAqn) = wnneaemtueyo 
‘[aeszzodey]dewtetd (anxzgn) = wnneaemoueyo 
/= “QQHW dAYS YQ wWorsZ st sueYOFouUMU “QueAe uo-ejouU TpTW 
eB go e3hq puooes eyQ "e"T) zequmu 870U PpeATeDdeI SYA St TEqUMNSIONTPTW x/ 
isueqosounu ,» TOQUMNSEIONTPTN (GLAGN) = yosTFZodeEW 


umyearmgueyo 
umNeaemzueyo 


iqueae uo-ej0u Tptu e butatecez ueym pesn st dewdketda e434 Moy st erey ‘D UL 


“suofqueauoD ouweUsTTF TOF Wuoumoop styA FO pus eyQ veg 
*(s@TTF ASTP peutquiod [Te ut Tequmu Te}I0R SYA JOU) OsTp WeYR UO 
peaes zequmu eyQ eq PTNoYs XGOH S,STTF YOO UT SEAEMFOUMN OGQ ‘OSTY 
“@TTF woPTAenuT{Quod ey A FO AGO SYA UTYATM SAM AxOEU SYQ YATM sumsoy 
*peaes ATeQeTduod eq ueD YOTYM SAEM ASET SYR TEATS OSTp T wo ETTF 
eqQy esoTo shemtw “FTeY UT evAeM oTdures e doyd zeAeN “ORe ‘Res {Tq 
UOFAENUTAUOD SAT SEARY USEAS PTNOD ETT styL “syunyo AGO pue ‘ACHW 
Zepeey ANWS UMO SAT SAeY PTNOYS ETTF uoTyAenuypqQuos ey, “pe_zeTer sy eq 
qsnu seTtTz oyQ Jo oeuweu SY “STTF S&,Os8Tp ZeyAoue uo st ezow yZeYQ 
ej7eotTput of Betz e& Aes pue OsTp SUO ojUO eTqtssod se yonu se dump 
02 St (eTduwexe rox 1-Za s,oTseD pue rz0eTdwes xz s,eyeuwex Aq peqerod 
-zoDuyt se) eotqoezrd peqdesoe eyy ‘“Addotz [ uo 3TzF 073 ebzeT 009 sem 

STTS AWWS 943 JT AnNDDO AYyhtu stTYyL “OstTp TeyQoue UO penuT QUOD ETTZ - OF ITE 


:BuTMoTtTos eyQ sueeu ‘jes ueym ‘eqkq sheta eyQ FO ATQ yqoeg 


*(3ufod etdues Azeae 20F GYOM B& peeu pTNom eTdures 3ATq 9T vW) “ALAG 

eTbuts e Aq pessezdxe oq ued evaem o4Q ZO eTduwes Areae QeyQ pue ‘AewToF 3Tq 8B 
ue st eqep otdures oy3 3eY4Q sueeU sTYyQ UWeYyQ ‘g = QeEUTO, JT ‘oTdurexe 20% 

‘eaem © Jo oTdues Azeao ut sqtq Aueotzstubts Jo zequmu syQ st eu, 


“STTZ punos eyA ut seaem Fo zequmu ey Atduys st soaemMzounN 


‘X[Tsnoeueqtnuys steuueyo ebtuy p TTe Fo 4ynd3yno eq of eAeM ZeqR ESNeED 
PINOm styL "Zequmu eveM cures OYA eq UEAe pTNoD se 3hq dewkeTa ey FO ANOF TIV 


(* queumsop 
STYQ UT TeVeT pessnodstp eq O23 ZqOW AeTd TANNWHO LINWONAdZGNI seumsse styL) 


“(002 st e3Mq deyketa qqrn0z eyQ esnedeq) y zequmu 
Teuueys otpne ebhtuy uo ooz eaem yoeq sketd zetdues eyun (p 
“(0 & st e34q dewketa patty ey esneseq) Aem Aue 
ut Z Teuueyo otpne ehbtuy Aoesze jou seop zeTdues ey, (€ 
“(€ st 0qMq deywkeTg puooes eyQ esneseq) T zequmu 
TeuueyS otpne ebtuy uo ¢ eaem yoeq skeTd z0eTdues ey, (Zz 
"(T st e34q denketg aextz ey esneseq) 0 zequmu 
JTeuueys ofpne ebhtuy uo [T eaem yoeq sXe td zeqtdues ey, (T 


ranoDp0 prnoys BHuyMoTTos eq ‘0 zTeqUMN ©30N TPTIW (sdeyzed 
yseQ TeyQouUe To Ax0d TeTzes ey worms) seaTtTeoez weshozd Bbuykertd etdues e jr 


‘00z‘o‘e’T exe deyketg zo seqkq py 3asatzy euL 


90P'dINVS 


retduexe BuTMoTToF ey Teptsucp “yoeq peXetd eq ptnoys zequmu 
HAWM ON 3843 OReDTPUT O73 peATeESeZ st QO FO Tequmu oveM dewketa YW “GGZ O23 T worry 
pezequmu ‘eTty ,dNWS., © UT seAeM Ggz FO TeQOCQ e oq UeD orEeYNQ ‘poeuOCTjQUEU sY 


‘py eq Of poeUMsse sT sUBYDFOUMN |syR ‘QuUeUMDOP sTYyQ FO yseT SYA ZO_ “sTeuueYyo 
otpne 7 sey ebtuy ey} eoUTS fF OF JES Eq TTTM SUeYOFOUMN 5 ,YGHW e4Q ‘ATTeNsA 
“szeqUMN S40N TPTW eETaTssod gzT eyy FO yore rox yoeq peXeTd oq of ere seaeM 

(Aue 3T) YOTYM eutuzejep o3 st Aexzze dewketTa eyR Fo esodand eyA ‘yoezszo ul 


*seqeyetdues qrnesep zteyR We Teuueyo Aue uo seaem yoreq Aetd ptnoys 

uot zeottdde ue pue ‘seaem oy z0z squowuhHtsse ejou Tptu ou ‘YqHW eYyy ut dewteta 
peppequy ou st ezeyR ueyR ‘9 = sUeYOFOUMN JI ‘Teuueyo otpne ebtwe eTqeTTese 
Kue wo zequmu oaem depwketa ey3 yoeq Aetd Atduts 09 WoeTe aybtw wezhorzd 

zeketd e ‘esed styuj UI “D9e ‘TH eAOoU Tptu oj suteqized puopes ey ‘o# e jou 
Tptu 09 suteqzed 034q ysatz eyg “dewAeta eyq ut e3Mq T Atuo sey ejou Fptu yore 
pue seqhq ect st dewketTa ey3 wey ‘T st sueyoFOUMN FI “sToeuueYyo oTpne ebtuy 

pb 943 FO YyOeS uo Auene punos e z0eHhHtz3 ATsnoeueqrtnuys prTnod z9equmMN 930N TPTN 
etbuts e ‘Aem sty ul ‘33e ‘T Teuuweyo otpne ebtuy uo yoeq AeTd 03 zequmu eaemM 
ey. st 034q puoves oy, *O Teuueqo otpne ebtuy uo yorq Aetd 03 zequmu eaem 

veya st e3Mq 4sztz eyQ ‘seqhq pF es0q2 FO “O# SION TPTW OF UTeQzed dewketa ut 
seqkq p 3satz ey3 ‘eTduexe zog “szequmu e70N FPTW BZT 944 FO HOWE z0F 

dewketa ey3 ut seqkq p ere ezeyz_ *seqkq zts st dewheta s,YGHW ue ueqQ ‘Pp = 
sueyosounn 37 ‘eTduexe zog *(gZT * sueyosoumn) Aq peutuxzejep st dewketa s ,udHW 
ue JO ezTs SUL “LZT 020 /(seyoqtd) szequmu ejou eTqtssod gzT eze ezeyQ 3eUR 
seqeubtsep 0°T coeds TPTN SUL “.ZAWM ON, S3EOTPUT O02 PeAZesSeI st O JO TequmU 
ARM ¥ "GSZ OF T worz pezequmu eze AeyL “eTTF .dNWS. & UT seAeM GGZ FO TeI0R 

e eq ued ezeyZ ‘“szequmu eaem Hutquesezdez seqkq so Aezze ue st dewdeta oy, 


‘yunyoUGHN { 
/*x ¥ OF 3TNEFEd “SeQON FPIN ETATSsod gzZT FO yore 
ZoZ esn OF szequmU eaeM YOTYM FO deue y/ ‘[pxezt] dewdAeta 
‘ped 
‘sueyosoumN 
/+ dewketa e432 Jo aadow Aetd soutuzejep »/ ‘epomdeta 
/= SUOTAOUNT SNOTILA SRLOTPUT SAT snoTIeEA »¥/ ‘sbeta 
/* 82-8 WOTZ SATq YUeOTFTUBTS TWNIDIUO FO # +/ ‘qeur0g 
/« ®TTE STYR UT seARM JO TequmU eUL ¥/ ‘SOAPMJOUNN ALAGA 
}qonz4s zepedx4 


/« ‘deyketa peppequt ey so ezts eyR uo quepuedep st ezTs YH x/ 
(8.10.1 WW) AIOXEN AGH AI eutzep# 


isqueuoduop HbutmMoTTos eyQ Fo 
SQsTsuoD pue Tepeoy ,dNWS, ©43 sMoTTOs ATexeTpeumy YUNYO ,AGHW. PeTTnbez eyL 


Sees sS=sS===S=====YJNNHO .UCHWN. FHL== 

[peumums syunyo quenbesqns [Te Fo sezts] Top syunyosoezts 
Jas, FOP anys 

ubTTe-pz0m: 2'O dONd 
L@ATT sxHootT styq ‘Atquesse ur 
(.4./ WW. N,'.S,)CIOXEW ANYS AI euTzep# 
:SMOTTOF se 
exe seqnqyz33e 5,31 “STTF punos aWWS © peeSepuT ST STTF ASTP Sy4R FT SuTUTEZEp 
03 pesn St STYL ‘“Tepeey ,aWWS. SU St ETTF punos e zo Hbuyuutbeq Azea ey a 


SS=SS==UICWaH udWWS., FHL 


20P'dINVS 





FORM and Chunk Registry 469 


IFF Specification 


/* STaq zoz Aue ZF []s3utoaoq 3sTT 
“Miwa zoz (Aue 37) []squyoaoa 3sT1 
*uofTqirod eseejTtez 
(dary peTToz3uop ebeytoa) 8,WOA e439 203 []3UTOdDA yore AsTT MON 
*uoTqrod yorqqe 
(day peTtTozqu0p ebexToA) s,WOA eyQ z0z (Aue 3+) []3uTOaDAT yore AsTT MON 
[X@epzxO STYQ UT SMOTTOF T# SAEM ATOZ SQEP 
eaem TeNQoe eYA pue ‘YSN ‘STUd ‘MLWd ‘3STU ‘uviw Aue zoz eqep eqE x/ 


/x "xXepeepeaem 43 FO pug +/ 


/« °83q3 ezouby wey ‘oO = 
SZTSUISN JI “MoTeq uoTQeueTdxe ees y/ 
/* @3ep resn ou weyQ ‘orez ZI 
*(edXqugsn Sutpntout jou) queufes 
eqep ButMoltoy ey3 Ut SALA FO #ox/ 


‘edxqugso aaomn 


feztsugsna 


‘sTaayoezts 


/» yaeubes sTad UT SALA FO # «/ 
‘MIWds0ez Ts 


/= yueufes YIVa UT SALAG FO # ¥/ 


/* *9zey OFUT e0AsS pTnoD noA ‘Hhuyz0eq{TTF TeathStp ewyareez-uouw 

Aue Bbutop eze nok zy ‘ueqy Tt3{UN * (xEATTA PETTOTQUOD ebeqtoa) 

JOA & OQexodzoouT TTTM oTpne ebjuy ezngnz WeqQ edoy eyQ 

Uy pepntout st sty, ‘“sesodind Huyze_ttzy xrozF edoTeaue reeUTT 
esta-soetd []aqutogog ue ufequoo squewhes sTud pue Miva SUL x/ 


/*« SMOTTOZ edoTeAUS JSTY ou ueYyy ‘O JI 
edojteaue asta juenbesqns ut saLAd JO # »/ 

/s "®A8M STYR TOF SREP YvGW ou weqR ‘oO FI 
‘edoTaaue YWLW Quenbesqns ut SsaLAd JO # »/ 


‘ozTsasTa 
‘@ZTSYWVLW ONO 


/« "“STFe{IOP TOF Queumdop y3eYR EES “XASE Se oues CYR ST 
(]autoa5g ue Fo eznQonzA4s EYL “XASS EXTT 3sn{ edojTeaue reEeUTT 
estma-evetd []jutogog ue ufequoo squewmbes asTY pue AWLY OUL +/ 


/= eaem eYR JO Hbutuutbeq eyy wory SLAG UT 
SOENTEA WESFJO SATSSEDONS QT suTeQUOD x»/ ‘[9T]STASLTEA GYOMN 
/« (€ e80q3 FO BNO Bq AsnU AT) UOTIODeZTP 
eaTtytsod = 79 ‘uOoFQDezTp eaTQeboU 
= 87T ‘oexzze AqyooTea ON = 0 ¥/ 
/*s YrFd Teupbtz0 yoreq sXketd qey  # SION FPTW SUZ x/ 
/x ‘oot ou ZF} ezTgeaemM O23 eS “spuUe eAeM 
943 FO wotqzod Hutdoot eyQ ezeym (eAeM OYQ FO 
eyq Fo Buyuuyzbeq eyQ wory) SALAG UT JeszzZO Ue x/ 
/* ‘oot ou JT eztsgeaey oF WeS “suTheq eaem 
ey Fo uoTpqz0d Butdoot eyqyA ezeym (eAeM OYQ FO 
eq3 Fo Buyuutbeq yA worTs) SALAG UT JoeszZzO Ue x/ ‘qzeqsdooT 
/« Y3td Teutbtz0 ye puoses zed seydues zo # »/ ‘eqeg 
/* Watd Teupbyz0 Ae spuodesoueu UT x/ ‘pofzed SONOTN 
/*x JueumrAsuT utegres e roxy Huyyorees roy pesn »/ fedAzsur 
/* sdamq TPTW 2OF GaSN AINO x/ ‘edAydoot aLAGn 
/* sdoumd TPTW Z0FJ GaSN XINO x/ sumndwestptW cdgxomMn 
/» (were eq LSOW) eAEM CYR UT SALA FO # T&ICR «/ seztseaem ONO 
} qonzqs zepedxsa 


/4ze4STe8A 
‘eQONQCCY ALXAGA 


ipugdooty 


ISMOTTOF se st erNQoNIzAs 
zepeoqeaem ey, “eqep sat Aq pemo[{Tos ‘zepeeHeaem 03Mq og ue sey enem Azeag 


(.%,'.0,',0,' 8.) QIOXEM AGOM AI Sutzep# 


*qI ue sey Ay syunyo 
TTS SATT “wWroF ,XASS, FYQ UeYR JUSeTEZFTP AIGWURCISNOO SF YuNYS .,AGOG. SUL 


SSsssssesss====NNOHO .AGOG. FHL 


20P'dINVS 


‘zepeesy e434 UT ezTs xequmu ppo ue HutMoTTe anq ‘seaykq Jo zequmu uenoe 
ue 02 4no yunyo e Hbutpped zo poyjeu agar TeotTdkQ eyQA asn LON od “AT Quenbesuoo 
ueASs Oq SAWMTV PTNOYS ezts s,yunyo ey, * (eTduexe sty ut eAhq TION exQxe SYQ 

@oueH) “seqiq Fo xzequmu ueae ue 03 Ano pepped eq SAWMTIW PTNo"US syuNnYS AWYN 


0 q°op 
earn! 0 qa°°opPp 
earn: 0’.bW oueta, q°op 
eaem: 0’,.T cueta, q°op 
eaem: 0’ ,umizqg ezeus, q’'op 

o€ T°oP 
/TAYN, Q°Op 


‘0 dONd 


[S8TYQ SATT YOoT ayHtu yunyo oyQA ‘Yunyqo oureu e pue seaem 

py peutequos eTtz e Zz} ‘etdurexe z0oq ‘ej4q TINN © Atduts oq 03 oueU 5,0AEM 
e zoz TebetT st 3I “970 ‘oureu s,0aeM puocoes eyQA Aq pemoTTos AToeyzetpeumy st 
AT pue ‘eaeM AsSITZ SYR TOF st oureu AszTF SyL “peqeuTUTey-TION st oureu yore” 
‘eureu © SAY ASNU SAEM KYFAT vsyy ‘STTF SYR UT pepnTouT st YuNnYS AWWN © FI 


(.3,/.W.' XM,’ .N.)GIOXEN ANN GI eutzepH 


Sossesssssssssssss=======YNNKD .ANUN, BHL===================== 


*pqe ‘szequmu eaemM TeYVAO SYQ XOF sures ey A op: 
zueys s‘beq 
UMNeEARBMTURYD q°AsQ TuUeYD 


‘(epowtetd INWGNGdaaNI Sutumsse) o ueyo ebtuy uo ejep: 
S,8ARM BYR AndAno puke ‘eDTASp oTpne 3yQ 03 pessed eq O03 pesu AeYQ senTen! 
ey3 eUuTUTeZep ‘ejep eTdures s,zequmu eAeM sTYQ JO sserppe syQ 30h Mon! 
queyo s*beq 
wUMNeAemMQURYo q‘4sQ 


umneaemeueyo’ (oe) q’*eaou 

umNeAeMzZUeYO ‘’+(OF) q° eacu 

umNeaemtueyo’+(0F) q* encour 

umneaemoueyo’+(08) q*eaocu 

oe‘op T'eppe 

oe ‘dewAeta eet 

SUBYOFOUMN X TSqUMNSEIONTPTH: op‘Tp Mathur 
Tp‘sueyosoumN q"eaocu 

_ TPR’o# beaou 

# eQou Tptu TeHbeTTt ue st styqQ se ‘ATxe: zequmn Tebettr s*yuq 
# SQOU TpTU peATedexr SeYQ ST STYQ-! OP‘TEqQUMNEIONTPTIW qq" eAcu 
oP ‘o# beaouw 


ISMOTTOZ se peqerdzequT st TEqUMNEIONTPTW PeEATEDeT e& pue 


[sentTea peztTeTqtut Jo seqhq sueyosoumN x 8ZT] asp dewketa 
[dewXetg zoz ejou tptu zed seqkq Jo #] q°->p sueyosFoUNN 
[zeqeT pessnostp gaow Aetd] q°op epowmAeta 
{xseu_4tq] q°op sbeta 
(qutod etdures e ut sqtq queotztubts so # eyA FO QunoD 93Mq e] q°op qeur0g 
[@TtTF eYQ UT seaeM FO # BYR FO QuUNOD 93Mq eB] q'op saaeMzouUMN 
( (ezt * sueyozoumn) + 9 st styQ] T°">p waHWFOeEZTs 
AGH, FOP aaHn 
z’‘0 dono 


[STYQ OATT SYOOT ern_0NzAs ,YGHW., ey ‘ATquesse uI 


90P'dINVS 





vices 


De 


470 ROM Kernel Reference Manual 


*Kzesseoeu st uoTsTeAUOD ON “9T = EUTO” §,MCHN SUL “QueoTsTUbTs 
buyeq s3Tq 9T TTS Y3TM CUOM & se peaes eq pTnom quTod eTdures 3Tq OT ¥ 


“(y Aq qubyx peaztys pue pepunoz) s3tq ZT 03 AOE pe_reauod eq ued 4F ‘TPT 

STA peqqtusuer3 ueyA qnq ‘eaeM 4Tq-9T eB se pejeTndtuew pue pepeoT eq Aew 

etdues ey ‘Aem styQ Ul “ZT = 3eutO”g 8,UCHW ECUL °(s3aTNSeZ eseqR eves 

03 ystTm nok pue peuzoszzed sem yReU ATG-9T MoS sseTuN) orez eq Aew ¢€ pue Z 'T ’0 
S3Ta * (AFT CYR 09 seDeTd YP GUOM 3TQ-ZT O43 AFTUS OT) “ST 03 p szequmu buted 
SAT FUeOTZTUbTs ea YITM GUOM EB se perojs eq pTnoys qutod eTdues 3tq ZT W 


*Kzesseoeu st uotszreauoo 
ON "8 = 3eWIOg 5,YCHN CYL “QueoTzTUbys Hbuteq s3tq g TTS WIM FLAG 
e se peaes eq ptnom (XAS8 SEATT) qutod eTdwes 3¢q g ue ‘eTduexe rox ‘os 


*seTdues eq uo yeu wrozzed oj reTsEee 
ST 3} SDUTS peTFT3snl-aseT eq PTNoys sytq quedTsTUbts eyy ‘ezowzeyzIng 


SNOT 8Z 03 LT 
qaom 9T 02 6 
aLA@ 8 
--W--W--W--N--W--W--W--W--N--W--N--W--H--N--W--N--N--N--W--N--H--W 
--+W--N--W--N--W--N--W--W--N--W--N--H--W--N--H--W--W--N--WN--W--W--N--H--H--W 
ezts quyod etdues anys s3tq queotstubts TwNISTUO 


ISMOTTOZ Se ANWS UT peaes Sym 
SeZTS eseqR JO SO 03 peRTEAUOD eq pTNoOYs juTod eTdues e QeYR peptoep ueeq 
sey 3— ‘SONOT 20 ‘SauoM ‘SanAq UO YEU wWIOZTed ATuo wed 00089 eZ eDUTS 


‘TIem se ehez03s ostp Jo wetgord eyy seatos Beta uofzenutquoo ey, “AemAue 
yoeqhetd uo uotsserduo> roxy peeu yonu eq 3,U0M oreY4R pequeueTduy ATTenQueAS 

st Suttdwes 3tq 9T ueqM “eTTS aNyS s,werbozd ezemajos zreyjoue ssexduopep 03 
moy ,MouxX 3O0U peeu, wexhord ezemazos Aue ‘ezoszezey, “TTeM se ostp uo Kem styR 
Qt ez0As 03 TeOTHoT sues AI “3eWIOFJ UWANIT UF Sq OF TpTuU TeAO peATedeT Be jep 
qoedxe prtnoys szetdues [Te 3e43 pepToep sem At ‘sqonpoad Teotsnu oze ereyy 

se 2eXTEU SYA UO seweYos UOTsserduOD eVep AueU se AsowTe ere ezeYyR eDUTS 

+ (eDezzeRUT TpTw e eTA) szeqnduoD pue ‘TeqyA0 yore ueemjeq e3ep eTdues ssed 

03 peeu szeTduwes Teotsnu esneoeq Aem sty3 dn jes sem coeds Tptu euL “STTF & 
Butpeot uodn uotssezduo> umo s3t op 03 uot IeDTTdde egy of dn st AI “PT 03 
qewz0g Ss ,NGHW ©8U3 30S “STTF punos e eaes nok ueym GuOM TeeuTT pessezd 

-wosep e& 03 ZLAG e3eP eTdues yore qzeauoD ptnoys nok ‘ehuex zeeuTT 3Tq PT ® 
sptetk ey} eweyos uotssezduos 31q g ue Sutsn exe nod zy ‘eTduexe Tog ‘oueyos 
uoTsserduoD UMO S3T ORUT QEULTOS TPEUTT SYR SRETSURTA OF SDTAEpP yore og dn 

ST AI “Reus zeeUTT e ut sdump oTdues satesex 03 Qoedxe pue QTusuUeTQ Qsnu 
ejep etdues butAetd Fo poyjeu Teuzequt zfeqyR Jo sseTpzebexr ‘szeTdues ofsnu [Te 
‘K~quezznp * (peds IGIW eq3 zed se) qewr0y TeeUTT UT pez0 ZS eq PTNOYs ejep oTdues 
esneveq st sty, ‘edXAq uotssezduos e butz0js rox AQTTFOeF ou st Sr0yR ‘OST 


"eAeM SYR UT ‘SCYOM Jou 

‘SaLAG JO Tequmu TeI0R SYR ST EzTSeneM YQ ‘eTdwexe TOF ‘eneM ATC OT & CAPT 

nok st 3euR Sf sueeW sty 2EUM “SMYIOM UT pesseidxe sezts sey ‘puey rey oO 

eq uo ‘dump etdwes TPTW SUL “SALAM UT SEZTS TTS YITM TeTsee Youu eq TTTM 
sjeszyo ssezppe SutAeTnoTeo os pue ‘00089 ET3 OF E3Aq © ST NYU UT ssezppe 
SATSsSeDONS Yyoee esneoeq st sTyL (‘o7e ‘ezTseaemM ‘qzeqsdooyt et) “SaLxAG UT 
pessezdxe sezts sey oeds sty ‘xeeddestp ATyoTnb TTT Huttdues 3tq g pue ‘oTpne 
atq 9T eaey ATqeqoad T1TM szeqnduop so uoTyzereueh yxeu eyQ ySnoyR uw68eAgq 


Sesssse======]NI0d AIdNYS TWACIAICNI NW JO FUNLONALS 


90P'dINVS 


T# ZAWM JO ANG ¢ 


*seqhq Jo zequmu uevAs ue 03 Ano pepped eq LSOW 31‘ 
‘ezTseaem sft queuhes styy FO (SALAG UT) EZTS SY, “SaemM OY4Q!/ 
zoy e ep eTdures Tenjoe eyA st (Aue JT) eQepxresn eYyW r9eQFW: 

*seqiq Jo zxequmu weve ue OF ANO AT! 

ped qasne ‘Aue st ozeqR FF Srey SRep Tesn eYQ SpNToOUT MON: 
UusSTa eyQ rox squtodog ey MON! 

WLWa eZ FoF squyodog ey Mon: 

ASTa eq4Q z0z squtodog eyQ mon: 

Aue Jt YWLW ©43 FoF (e3ep) []squtodgg eyQ epnToUT MON! 


“styq ezouby weqQ ‘9 = / 
@zTsugso JI “MOTeq uoTZeUeTdxe ees / Mop 
eqep zesn ou ueyqQ ‘orez ZI: 
- (edAqugso Bbutpntout you) yueuhes: 
eqep zosn HutMoTTOS ey3 Ut saLAd FO #5 T'OP 
queudes sTud Ut saLAG FO #/ TOP 
queubes Miwa UT SaLAG FO #/ =T'OP 
ejep gsTa ou ueyy ‘Qo ZI: 
edojteaue ysTy quenbesqns ut saLxq FO # 
“@sAeM STYR TOF SRep WWLW Ou ueyQ ‘Oo FI 
‘edoTeaue wwiw quenbesqns ut saLAd FO # 


edxjquasa 


oztsdasn 
eztssTad 
OzTsuLwd 


T°op eztsasTa 
T°oP OZ TSYVLY 


sqeszzo AqyOoTSEA 9T FO THLOL & TOS"**! PT MSP 
pqje***[qeszzo AAtTooTeA puocDes] M°op 
[qeszzo AqypooTea ysztz] : mop STAPLTSA 
{[ezt zo ‘po ‘o]: q°'op 3zeISTPA 
[yoatd Teutbtx0 yorq sXetd 3eq3 # 230N TPTW 943) q°op @IONIOCN 
[spue osaem ey Jo uotTqIr0d 
Butdoot eyQ ezeym of (eAeM OYA FO 
aya go Sutuutbeq ey wory) SALAM UT WeszzZo ue) 
[’sutbeq eaem oy3 JO uotTAz0d 
Butdoot eyQA ezeyqmM OF (PARK SYA FO 
ey so HutuuthSeq eyA wory) SALAM UT WeszzZO ue) 
(yoatd teutStz0 ye puopes red setdures jo 
[yoatd TeutHtz0 ye spuopesoueu ut potire 


s 
4 


T°op pugdooT 


T°°p qazeqsdoot 
T°op e7e8 
Top potzed 
q°op edxysul 
q°op edkydoot 
mop umydures tPTH 


Pu Ne re 
on 


wen rene 


sdumd }PTW 203 GaSN X'INO {t zo 0] 
sdumq TPTW 20F GaSN XINO (dumq etdures tTptW woxzz] 
[(wese eq ISON) e4eM STYR UT SALAM FO # TeI03]/ TOP SZTSOAEM 
@AeM ASITF SYR TOF MON ?: 


4 
s 


[zepeey e7Xq g butqunod jou yunYyD AGOM e432 UT seqhq Te}03] T*op Apogzoezts 
,kGOa, GOP uadwaHApog 
z‘o dono 


ISTU OATT sYooT yunyo zqog eu ‘ATquesse ul 


/s PACM ASITF SYR se wIoOZ owes CYR 

ST I “MOTTOF MOU PTNOM CAEM AXE OYA TOF Sep pue TEpeSeYOAEM SUL »/ 

/* T# ZAYM JO GNA x/ 

‘oyurwmzogeaem { 
/» *803hq Jo zequmu ueAs ue 03 Ano pepped eq LSNW FI “SZTSEAEM ST BRep STYR FO 
(SULAG UT) EZTS CYL “eAEM EY TOF eQep eTdues TeNQDe eYQ ST eTCeY ‘AUTeura 


“qeyQ joeTser ezTsuzsn eaey pue seqyAq Jo requmu weve Ue OF 
qno 31 ped jsnc ‘Aue sft ezeyy JT eTEY eRep Tesn oy R epnNToOUT MON +¥/ 


90P'dNVS 





FORM and Chunk Registry 471 


IFF Specification 


AAypOoTSA FpTw FI 
AqTOoTSA TpTw ZI 
AAyTOoTSA FpTw 
AqyooTea TpTur 
ARTOOTSA TpTw 
AAPOoOTSA TpTw 
ARypOoTeA TpTw 
ARyOoTSA TpTw 
AATOOTCA TpTu 
AATOOTSA FpTw 
AAypOoTSA Tptur 
ARyPOOTSA TpTw 
AATOOTCA TpTu 
ARZPOOTSOA FpTw 
AATOOTSA FpTw 
AAzTooTea FpTw 
AAzyooTSa FpTw 


[o]eTqeLTeA + x3aeTdues Qe Q2eRS USER ‘LZT O23 OZT 
{tT]eTqeLTeA + z3aeTdUeS Qe 47BR9s UEYQ ‘ETT OF ZIT 
[z]etaesteA + r3aGeTdues Qe QITeQS BENQ ‘TIT 99 POT 
[e]oTaeLTOA + xr2aeTdUeS Qe QITeQs USeYyR ‘E0T OF 
[vy] ©TQeLTOEA + z3aeTdueS Qe QTeQs eT ‘GE OF 
([s]eTqe.TeA + r3aeTdUeS Qe QzeQs USER ‘LB OF 
[9]eTqeLTeA + z3aGeTdues Qe Q7eQAs WeYR ‘TS OF 
{L] ©TaeLTOA + AAaeTAMUeS Qe QTeQS UEeqQ ‘TL OF 
[eleTtqeLtea + z3aeTdures Qe QreQs UeYyQ ‘£9 OF 
{fe6leTaeLTeA + r3aeTdues qe QreQs uSeYqQ ‘Gg OF 
[oT] ©T42LTOA + T3aGeTMUeS Qe QzTeQs WEY ‘LY OF 
[TT] STAeLTCA + 23aeTdueS Qe ATeQSs USER ‘GE OF 
[ZT] ©TARLTOA + 7QaeTdUeS Qe QTeQS USEYR ‘TE OF 
[eT] ©TQeLTOEA + z3aeTdWeS Qe QTeQsS USEYR ‘EZ OF 
[yt] ©TqeLTOA + TQaeTdWeS Qe Q4zeRs WENA ‘ST 02 8B 
[st] ©TqeLTeA + z3aeTdures qe AeTd qzeqs ueqy ‘L 03 T 
JFO SQ0u e& st styQ ‘oeTdues e AeTd 3,u0p ueyQ ‘oO 


Feet eee teet 


Vrnonrnrnrhtnnronenennnn 


“qzeqs ARyoOoTSEA FAILWOIN 
eTqez © ST ETOH ‘SpIeMyOeq YOM pue ‘STGELTEA FO GNA ey worz qreqs nok 
‘KAPOOTSA FpTtu ut squeweToOUT g yore Toz wey ‘(82T) AAILWOIN = 37e3STSA FI 


‘uoTantosez ySnous epfaoad ptnoys etqey sty, ‘“peejuezen6 st 

»S¥OTTO, oFpne ou ‘Aem sty, “r0QTpe ue eta shuyssoxo ozez uo jes ATTeTATUT eq 
eq ued sjeszsFO OYR AEYQR OS ST OTGeEQ e KHutaey ox uoseex eyL ~,ATZ SYR YO, PeeT 
-noTeS st jutod 31e4s ey JT HuTssozr oxez e eq prnom eTdues Suyyrnsez eyQ WeYR 
utTeAIED eq TeAeU PTNOD AT ‘osTe 4ynq ‘moTs eq ATuo jou prTnom styL “37e4s eTdues 
ey 3 PUTF OF UoOTsTATp zebequy esn pue zoRDeZ eTeDs e AzyToeds 03 QueM 3,U0P OM 


ARyOoTSaA Fptw FI 
AAyTOOTSA TpTw 
ARypOoTSA TpTw 
AqzyPooTea TpTw 
AyzPOoTSA TpTw 
AAyPooTea TpTu 
AqypooTea FpTu 
AAZPOOTSA TpTwW 
AqypoOoTSea TpTw 
AAyPooTSA FpTur 
AZyooTSea FpTuw 
AzyPoOoTSeA TpTu 
AyyooTea FpTuw 
AAZTOOTSA TpTu 
AqzyooTea TpTw 
AqpooTea FpTu 
AqypooTea Fpyw 


[st] ©oTqeLTeA + z3GeTdUeS Qe 42eR5 UEYQ ‘LZT O23 OZT 
[yt] °TqeLTSA + r3aeTdueS Qe 4zeQs USER ‘6TT OF ZIT 
Cet]©TqeLTeA + r3GeTduUeS Qe 4TEQS USYQ ‘TTT 03 POT 
[ZT] 9TASLTIOA + r3aeTdues Ze AIeQs USEYR ‘EOT OF 
[TT] °TqeLTSeA + t3GeTdUeS Qe QzeQs UEqR ‘G6 OF 
CoT]°TaeLTOA + TQaeTdueS Qe QzeQs USEYR oF 
[6] STaeLITeA z3aeTduwes 4e Q2eQ5 WER ‘6L OF 
[e]eTqeLTea + t3aeTdues Qe Q7e9s UeYR 0°23 
[L] ©TUeLTOA + T3aGeTdUeS Qe QITeQs UEYQ °F 
[9] ©TQRLTOA + zQaeTdWeS Qe QTeQs UeTR °F 
[s]°TqeLTSA + TIaGeTdUeES Qe QITeQs UEYqQ °3 
[v]l©TaeLTeA + z3aeTduwes Qe Q7eQ6 UeYy °F 
Ce] STAUeLTIOEA z3qaeTdues 3e Q27eQs USeYQ oF 
[z]©TaeLTeA + z3aeTdues Qe Q2eK48 U)EeTyR °F 
{t]etTaeL,teA + z3aeTdueS Qe QzeQs WENA ‘ST 02 8B 
Coletqeztea + t3aeTdues qe Aetd qzeqe wey ‘2 02 T 
JZyFO Sj0u e& st styA ‘otdues e Aetd 3,u0p ueyqq ‘oO 


Fee eet eet 


‘eTdures oy3 zo Sutuutheq eqz 03 squtod z3geTdues “327e9STSA AAILISOd 

zoz ssexzppe yoreqKetd q2eqs ‘sa AAyooTeA uo-ejou TpTu peafecex HupAeTex eTqeq 
& st ezeq ‘ssexppe eq We yoreqheTd qzeqs pue ‘(joyseuo Jo A7eQs) sseIppe 
Sbutuutbeq s,esem ey 03 3eEs8FFO STIR ppe ‘ETQeQ OYR UT dN evo NOX ‘QO SACGE 
AAFOOTCA FPTW UT sjueueTOUT g yore roy ueqA ‘(~9) AATLISOd = ITEISTSA 

JI ‘entea butpeserzd eyA (03 Tenbe 20) ze3eexH eq pTNoYys enTea satssoDons 
yoeqg ‘oaem 043 FO Hutuutheq eyy worsy sJeSsTFO ALAC 9T SUFeAUOD STQeLTEA 


*(@ARM STYR FO SEARQDO peQeTodzeqUT TSEeYyQO ou ere erTEeYR WeYQ 

qdeoxe) ets XASS Ue SXTT yenf eaEM EY FO suCTAIOd zeqQO omy eYQ yORq AeTd 
pue eqep ,b5utTtez3, styq ezoubt 03 esocoyo ues nox ‘“AuTod styA zeqze ejep 
exom TIT3s eq 34ST ezey3 sdeqized zo ‘Azoweu ut eaem ey JO pue Area eqQ 0q 
aySyu styl, ‘“spue uotqzod butdoot eq3 ezeyqm 03 eaem OYQ Fo Hbutuuthbeq eq worz 
qeszzo ALAG © BST pugdooT ‘eaem OYA FO woTAI0d YoYyseuo eYA st uot ZI0d HbutdooT 
ey FO ATeAs eYQ.09 dn oAeM OYW FO AIEQS EYQ WoTZ eQep ey, ~*seTdurestyyeeder 
se 03 pexrzeyex sem wotqzod buydoot eya ‘xASE UI ‘UoTAr0d butdoot 

ey3 FO ssezppe AzTeQs EY st AreQSdooT + eQegeTdumes vey ‘eAeM OYQ FO QITERS 
eYy3 09 squTod eqeqetdues sy ‘eTduexe z0qg ‘sutbeq eaem oyR FO uoTqQIod Hbufdoot 
eyR ezeymM of eveM SYR JO Hbutuutbeq eyR worsy AesFFO ALAA & st yreqgdooT eyL 


90P'dINVS 


“Kem styq2 3¢ op 03 nok steduos 3eqQ 

qewroy aNyS e49 uT Butyjou st ezeyq ySnoyy ‘yoatd esodsuexy 03 Aem yseqsez 
eyy eq 03 esord ptnoys styL “spotzed zo etqeq ,dn yooT, e& Sutsn umoys oq 

TIt* yootd Hutsodsuerzq jo poyjzeu e ‘zreRZeT (“sXDOTTPTOH peutetoxe ‘,{LHOTIU Lsac 
st potzed stuz,,) °. (peTduwes) pepzovez sem 31 se, ATAOexe yoerq peXetd oq TIT 
eaem oyQ ‘potrzed joexe styq ButAztoeds Aq -peaetyoe eq TITM youtTd zeybty e pue 
‘xeqsez otdues oy yxoeq Aetd [T[Ttm ebtwe eyQ ‘entTea potxzed zemoT e BbutAztoeds 
Xq “peaetyoe eq TIT yootTd zemoT e pue ‘zemoTs setdures oyQ yoeq Aetd TTT 
ebtuy ey ‘entea potzed zeySty e Butkztoeds Ag ‘entea potzed sty  ,esodsuez3,, 
03 peeu ptnom suo ‘seyoqtd remot zo zeyhty Ae eaem oyQ AeTd 03 zepzo ur 


- (xehequt ue 03 pepunoz) 6.1 = potzed SHuttduwes ano pue seoetd 9 3yHTx eyQ of 
aoetd Teutoep eyy esocu ‘spuocoesozDTU Jo suey ut pofzed eyQ ees of speou ebtuy 
ey3 SoUTS *(UOTIEQTWTT eTeMprey e) ToROe, eHpng ebruw eyy st S9EELZ™ STOYM 


G9€6LZ° BANA AUWMGUYH OLGnY euTzepH 


LLEBLTOOO" = S9E6LZ‘/ (00002/T) 


:eq pTnom poftzed Suttdues eyQ ‘yootd 
TeutHtz0 s,3t 7e eaeM OYyQ AeTd 03 ueqQ ‘000072 = eIeY JT ‘eTdwexe toyz 
“yoatd Teuthtz0 eyA Jo puoses red setdures yo xzequmu ey Q st o7ey SUL 


“¢ ZequMU 9870N TPTW Z0F seziq 

dewketa ey3 ut petztoeds 3,ust 3t esnedeq [Te We peAeTd eq jou pTNom pF eAeM 
ueyy ‘€ TequmU e70N TPTW eATOEDeZ om JI “YyouTd TeuthHtz0 s,3t ueyR reybty deqs 
sTeY & (T Teuueyo uo) peXketd eq ptnom pF eaem ueYyy ‘7 TEquMU 930N TPTW SATeDeZ 
em JI “yoqtd TeutHtx0 s,3T uweyR remot, deqs zTey e (¢€ TeuUeYD uo yoreq peAeTd eq 
PINom py eaeM ueYyA ‘oO zequMU 930N TPTW & eATEDeT OM ZI “YyORTd TeuTHbtz0 8,37 3e 
(9 Teuueyo eftuy uo) p eaem yoerq AeTd ptnom T zequmu e30N TPTW Sutatesex ueyQ 
‘T = SQ0NQ00Y 5,7 OneM Qos OM ZI * (ATOATQOedsSeZ [T pue ‘Oo ‘Eg sToeUuUeYyo ebtuy 

uo) p zequmu oaem Ketd 09 Aes [Te eze Z pue ’T ‘O SOION TPTW 3LYQ SOTION 


" €# S9ON TPTW x/ {°° °T’T’2%‘09 
" . Z# S3ON TPTW x/ 0/0'r'T 
/* 4 " T# S20N TPTW x/ 0‘T‘00T’? 
/« Jueuubysse Touweqo O# ©30N TPT +/ v‘o’0’z} dendeta 


:dewketa 
e Jo Adzeoxe HuTMoTTOs ey TeptTsuoD ‘eTdurexe z0oqg “youtd peprovez ‘Teufbtz0 
6,37 3e yOeq onem oyR AeTd TIT ReYR Tequmu O70N TPTW SYR ST SIONQOCY SUL 


"9 02 
Aes Oq TITM 31 UeRzZO “QueUMdDOP sTYR FO pue sYyW We peuTetdxe st edAysurl oeyL 


‘dump eTdues IGIN © wory OFUT PTOY oF 

pesn Atuo st edAzdooy eyA ‘estmextT °,,xoeq AetTd oj eaem ou,, uPeUt O72 peATEsOT 
ST 0 JO zEquMU SAEM e AEYQ TSEqueUeEY “SeTTF SYR UT EAREM YSATJ Vy FO Tequmu oyQ 
Buteq T y3tM ‘Ggz OF T ueemqeq ere dewkeTd 943 ut srequmMu eAeM 9YQ ‘OSTW “STTF 
aAWS & UT pecsetd oq prtnoys eaem eYQ ezeYyM uo Hbutxreeq ou sey 31 “dumq eTdures 
IGIN © WoIF peATedeT Tequmu eTdues SYA PTOY OF pesn AINO ST UMNdUeSTPTW SUL 


({SULAG 4O UFANAN NAAT NW OL INO WiWd GHL awd) “pT = ezTsenem ueqy 
OT‘2T ‘ZT ‘00 ‘0v- ‘SE- ‘0e- ‘on se ‘0E ‘09-’08'06-’00T aLAG 


isetdues 31q g SutmMoTTos eyQ Fo peqstsuoD ejep eTdues aznoX ZIT 
“eTqe} eTdues s,eaem e439 UT SALAM JO Tequmu eYyR ‘pejzeqs se ‘ST EZTSOEAEM SUL 


poutetdxe repeoqoaem oyL 


90P'dINVS 





vices 


De 


472 ROM Kernel Reference Manual 


28Fq3 SxYTT edoTeaue xzeTsTTdwe ue eQeeTDeT 03 ‘os 

‘gueumoop xase TeutStz0 43 ut Aq tnhtque eq; da szeeTo sty3 3e43 edoy I 
‘euMTOA £,5a snojzaerd ey worry EdUeTEZFTTP S se You ‘O°O WorTZ peuTUIe ep st 
eumToA 8,52 yoeg “qutod uteqsns oqy sXkemte st wwiv O43 UT AUTOdo” AseT SUL 
("ONTeA sTYQ Peesecdxe pTNoys ZoOADeF ouMTOA ON “O°T) “STQTSsod eumMTOA WOWIXWN 
eyy squesezdez (0000T000$) O° T ezeymM QuTod pextz & ST ZOQDeF ouMToa eUL 


['quby2z ey3 03 9T pue qutod Teupoep: 
42 FO 3FOT OUR OR BATT OT ‘QUTOd pexTsZ - zrOQDRZ euMTOA eR)! T°OP 
[spuccestIT Ta uy woTZeINp eyR]/ M-Op :TIUTOdD” 


ISMOTTOF se erngqonzys e3hq 9g e& st Autodog eThuts w 


sse=asss==2===s=== (r0oqereueh edoteaue) 3utodoq Ny ==========: == 


eunToa pue ‘47eQs eTdues FO ssezppe eYq3 ETE OP pue OF MON---! 


eumjtoa ebtuy queteatnbe ue! op‘t# a bppe 
z Aq epyatp: op ‘T# q°zs—T eUNTOA 
eumjtoa ebftuy ue 03 A3TOOTeA TPTW yreauOD---: 


yoeqXetd Tenjoe 32e348 03 ereYyn! oe ‘Te T° eppe 

qeszzo AAtpooTea eyQ 306! te’ (Te) M* ACT 
spzeayoeq of! Te‘Tp 
Na #,eTqQe2 3e 37eR8/ Te ‘OE+STIRLTOA 
PIOM & YOREF 02 poeoeu em osnEded Z x! tp ‘tp 
8 Aq eptatp: Te ’c# 
AzyooTea ejeotTdap! TP ‘op 

qeszzo AyyooTea eat Qeben---! 

= TeAeaT {Ebon 


oUMTOA s°ezq 

yoeqKetd Tenjoe 37e4s8 09 eTeYA! oe ‘te T° eppe 

qezzo AqzpooTea ey 306! Te’ (Te) “°eACw 

paeazoz ob! Te‘Tp T°eppe 

awaH 8,©TQeQ 3e 31eR8/ Te ‘STAeLTSA eet 

PIOM & YOReF Of peow em OsNnedeq Zz x: TP ’TP q°ppe 
8 Aq epzatp: TP ‘e# q'z8T 

Ajyoojtea eect Tdnp! Tp ‘op T° acu 

qeszzo AqpooTeA eataTsod---: 


(8ZT) ¢HATLVDEN 37 ST! TeAeatzebon s° yuq 

© FT EUFAnoz yeszzo AqyTooTea ey dtys/ eunToA s*beq 
TP’/3283STSA =" PAT 

UoT{QDeITp pue ‘NO ernqeez QzeQs AQTooTeA z0z YyOoyD---/ 

LZT < AqypootTea peafeoex Zt 3Txe: TOA Teberttr Fuq 


-ebessou zZo-e jou e sseD0id: = 
03 eUFQNoZ e 03 Youerq ‘ozez JI: FFOCION W beq 
efessew tpru e so e7fq AqzooTea eya! op ‘AR FOOTeEApEaTedey q°eaou 
oP ‘o# beaow 
eqep etdues eyQ FO zppe yzeRs ey: oe ‘eqeqeTdues eet 


‘Kiquesse ur 


90P'dINVS 


/x 2aem CYR yorqkeTd MON x/ 
/x eumpoa yoeqketd x/ ‘T + z/AqyooTeapeatesez) = eumqtoa 


{ 
i [Azqugetqe3 - sT]eTqeates + z2aeTdues = eaemzoz7eRs 
/* AALINDIN 34 SI x/ } 
(8Z7T == 37e3ST®4) ae 
/* aTod yzreXs eTdures eYQ putz OF eZEqM, »/ 
/[AxrqugetqeajetTqe;tea + z3aeTdues = eneMzozTeRs 
/* FAILISOd 3F SI +/ } 
(p9 == 3zeQSTOEA) JI 
‘g / Kayoote~peatessy = AzqugeTqe> ; 
(0 =i 7eQsTeA) ZI 
/» ebessou tpt e yo e3Aq AqpDoTeA eq3 x/ =} 
( 8z— > Aapootea~peatesey 39 0 =i AzFOoTeAPeaTeDey ) ZI 


9 uz AQypooTea FpTu peateosez e AueuweTduy 07 Moy JO eTduexe uy 


“(0 zo KayDoTea Tpru peafeser e rox Hutyooy> ugLgy ATuo 3nq) 
T ppe pue z Aq peptatp eq prnoys AjyooTea TpTw peafecex e ‘efuez TpTu eq 
JO ZTeY ST STGR EDUTS “P9 OF O ST SUMTOA TeuUeYS ebhtuy zoz ebuez TebeT euL 


“(JFO eQou e se peqezdzequT eq SXYMTW PTNOYs 
0 30 AqyOoTeA TPTW ¥) “LZT 03 0 8F seqkq ARpOoTeA TPTW z0z ebuez TebeT eqs 


semas==ca===3WO10A TENNVHO WOINY “84 ALIOOTSA IdIWs=22===== 


“geNTRA STAB 9T SYA SsCOYD 4seq OF MOT 

uo osut TOF ,eTQeZ AZTOOTEA eYQ HSuTyXeW,, UOFQOes EYQ SES “EANZeeZ STU STAESTP 
/eTqeue oR zesn eYyy MOTTE ues werborzd uoTaeottdde ue ‘osty ‘uot equeweTdut 
@IEMZJOS S CTA OFASTTeST ETOW SOEARM JO SPUTY Sse SORXEM ZISISTSA “sSeuMTOA 
quezesstp 3e syoeqQe QueZesTTP ATqTYxe (D390 ‘souetd ‘szeqtnb ‘sutTota) 
sqjueunrzsut pexontd pue pebuyzqs ‘ezowzeyzang ‘efuez oumqoa #37 qnoybnozy3 
queunzgsut sat JO uwoTZeRUesezdez enzq e sptTetTXx eaem ouo ‘Aem styQ ul *“yoeq3e 
TeTATUT eqQ ue_zos 03 puey AqezeyR pue setdmes Gupuutheq eyz wdtASn TTT 
AqyooTea Tpyw TemoT e ‘OTGeL eqy uF sqeszzo eyQ dn Hutz3es8 pue enTeA FATIVOIN 
e 09 azeasten butaqqes Ag “pxeq 3tq Suteq exeus e pzovez aybyu nox “prey 
YOnTAS ST AT UEqM ueYQ peouNouord sseT st YORQIE TETATUT sqy ‘eumToa 4zos & 
U3TM ATW sf umzp ezeus e veya ‘eTdurexe ue sy ~ernjees sty FO OsN SYR ST IEUM 


‘sqeszyo Jo eTqez ey Aq peqoessze eq AOU 
Ptnoys qzeqs yoeqhetd s,eaem eyR wey  ‘(0) SNON OF 308 ST ATEISTOA FI 


“Q7B3STOA ZAILWOAN Joz eaem yA Jo Hutuutbeq eyR pxreM0Z ART 


qutod 32e3s ey sbutzq, AypooTea Fpyw HuyseexouL “ATeISTSA AAILISOd TOF 
SARK OYQ ,ORUT rEqQTeZ, yoeqhetd sqzeqs Aqyootea tptu Huyseezouy ‘oeouesse ul 


90P'dINVS 





FORM and Chunk Registry 473 


ification 


IFF Spec 


“s, S se oues oyQ st 03Xq yewz0s otdues s,dumq TPtW YW 
T = pxzemzoz/pzemyoeq ‘9 = premr0z 


ISMOTTOZ se st edAqdoot eyQ ueyA ‘os gr “sXem snoyiea ut ,e {ep 
oTpne butpeez, sqzoddns ezempzey ebtuy sseTun/TTqQUN esTMTeYy jo AT ezousT 4nq 
‘ezxey 03hq edXzdooy s,dumq TPpTW S43 eT0RS pTnoys nox “ATuo preazoz syzoddns 

ezempzey ebtuy “premyoeq/pzemiog XO ‘pxremz0z eq ued edky doot s,dumq TpIW W 


‘eUeD AT SoUEYM WoTF QUEUMAQSUT TPTW EUR OF YOR EABM SYA pues OF pes 

noX [7qun zequmu styR ynoge yehxroz ueyL “pTeTy umnNdwestpiw s,dWWS UT (3SITF 

aS'T zepeeq dumq ey3 so seqkq yA9 pue y3G¢) xequmu eTdues eyR ez0js qsnf ‘dum 

etTdues IptW © Butastoez ueym ("eAeM BUO UO OJUT spues ATuO dumq eTdues TptW 

‘eTbuts vw) “Ssz 03 T eq ysnu dewheTd eyQ ut szequmu atey 3 pue ‘seaem ggz o3 dn 
PLOY ued STTS aWYS W "SESS9 OF 0 eq UeD Tequmu eTdues s,dump oTdues TPIW VW 


‘SLAG UT pessezdxe squeTeatnbe gNwS e434 snsz0en 
S® SCYOM UT OsTe eze AuTod pugdooy pue jutod jzeqsdooy s,dump eTdues TpIW ¥ 


@ x yqbueTeTduestptW = ezTseseM 


ist dtysuoypqertezr eyQ 
‘(ptdnas AtTqtpezout ey z04a) “SaLA JO Tequmu eyR ut pessexdxe st ezTSeaeM 
S,dAYS “SCHOM UT pessezdxe st (zepeey dumg eyQ Jo sezhq y3ET pue ‘YIZT 

‘"aQTT ©q3) dumq etdures tptw e ut (yqbueT s,eaem) seTdues Jo zequmu ey3 OSTY 


6401 X (2eaeTduUeStTPIW/T) = e784 


rdtysuotqeTez eyR st ezey ‘eTTF dWvS e& Jo eQeU eYyQ pue ‘TegeTduestptTn 

TTR TIT om yOTYM (382TF AST repeey dumq eyR Fo seqkq yQoT pue ‘UIE ‘UI8 

ey3) dumq etdwes tptw e JO pretz potzed etdues eyQ eyeq noX JI “puodesozoTu 

qsezeeu ey3 03 pepunoz potized sqt ves 03 speeu ebquy eyy © (Aouenbezz) puooes 

xed setdures zo suzeq ut yoeqheTd sesserdxe osTe qWWS “spuoDesoueu uT GOlugad 
etdues e yo suey ut ATuo oqex yoeqXeTd setztoeds dumq eTdures TpTW eUuL 


“(sdump fptu) seaem esayQ FO Ggz o3 dn ptoy oj peubtsep st eTTs dN¥S YW “enemM 
ano dn seyeu jeyq3 ejep etdures ey3 [Te spues dumg etdures tTptw e ‘ezozereyL 
+, 8AM B, TTRO om Aeym dn oxyeu jeyq squtod etdures Auew yo uwofQoe{T Too 

e sueow 47 Attensn ‘oTdues e Anoqe syTeZ SANVeTSATT IGIW USeYyM :SOLLNYWGS 


/* 299°°° x/ ‘gdoolTq2e4s 
/+ TdooT Fo pues ayA oj eTdues eyy 
yo butuutbeq ey wory ZeszZo ALAA x/ 

/x Tdoot Fo 3xeAs eYQ OF eTdues sYQ 
yo Buyuutbeq ayy worzz Aeszzo GLAM x/ ‘TdooT_7eIS ONOTN 


‘tdooypug 


/x MOTTOF 03 squtod doot zo zequmu y/ ‘sdoo yzoumu quomn 


rQeurey sty UT pezojs eq ues osut Bbutdoot 

Teuotatppyw ° (Attzewtad sqonpozd otsep) doo, euo 

asnf uey R ozou moTTe 3ey3 szeTdures ewos ere ere] 
-etdues eyA xox squtod Hbutdoo,t ezouw sutequoo styz - (€) ONIdOOT 


90P'dINVS 


‘eaem oyQ AetTd 03 Wes Teuueyo 

ey FO Toeuueyo TOReTRpou syQ OF QUeS eq TTTM eAep 

stu~ ‘zeqstbez NooMaw ey3 Aq peqtzosep se Teuueyo 
ehtuy ue Jo uotzeTnpow potrzed azoxy st eRep STYL  - (Z) Gonugad 


‘eaem eyQ Aetd 03 Aes Teuueyo 

ey FO TEuueyo ToReTNHpow syQ OF Ques eq TTTM eQep 

sTyL ‘zeqstbex Noouaw ey Aq peqtzosep se Teuueyo 
ebtuy ue JO uoTAeTNpow sumToA Toy st eRep sTYyL ~- (T) COWTIOA 


*eqep osyq ezoubt pue ‘,estTe euoeuos, Aq ezeyq and 

SPM SREP SsTYQ AeYQ EpNToOUCD pTnoys AT ‘eztTuboo 

~8Z UBD AT WeYQ Tepeey JO 4yTOS sSUIOS pUTFZ 2,uUsSeO0p 

uotqeottdde ue pue ‘olarIogas st edAqugsn 243 JI 

(Aeros AWWS 943 ,UTYRTM QeUTOZ, eB "8°T) “eztubooez 

AjTe_etpowumt ued uoryeottdde euios yeyR euros e UT 
pezojs eq prTnoys 3r ‘eqep oTztoeds uotaeotTdde - (0) OLaIogds 


€ ONIdOOT eutzop# 
Z dowddd euTzyep# 
T  dOWIOA euTsEPH 
0 OlaIogds eutzopH 


:eze sedXkq 

Quezind ey, ‘pez0js st eqep Jo puTyY 3eYyM sTTeR edAqugasn s,repeoHeaem oyL 

‘ogut otTstoeds uotqeottTdde ‘zeyjo zo ‘oyut ezempzey ebtuy ezojs ues uotjeottdde 
ue exeUM ST STYL “eAeM YORE TOF eQep Zesn Hutzoqs roxy uotstaord e& st ereUL 


NOILOGS WIV WISN TWNOILIG 


O ST sumTOA Ya: 00000000$ T° >P 

oOoT MOP 

oo00~v0000$ TOP 

ootT MOP 

ISmMoTTOZ se p ebeqs Aztoods pTnom ejep ASTa eyy MON 


(¢ efeqs Ae Butptoy mou eze em) “szoO! 
peurny st ejou eyQ TT3un (NIVLSNS) PTOY eM ezeyM st sty! 00080000$ T°eP 
oot TOP 
TeaeT styy 02 FFO AOVG! 000D0000$ TOP 
oot #°Op 
z ebeqas: 
suMTOA TTNF st yoOrQQe Ino Fo ,xeed, 943! OOOOTOOOD$ TOP 
ooT Mop 
000D00000$ TOP 
oot Mop 
oooso000$ TOP 
oOoT MDP 
stya 03 06! 000n0000$ T">P 
swooT exe9! ooT MOP 
T ebeqs: 


[OS CATT ‘EQep MWLY EUR UT eq pTNom € pue ‘z ‘T sebeqs 


90P'dINVS 





vices 


De 


474 ROM Kernel Reference Manual 








HOLId TYNIDIUO 






/x YrTd s,ejouQ007 »/ 


‘TTZ /x  eu0gtues 7Z/T NMOC +/ 
‘Ezz /x seuoZtues T NMOG x/ 
‘9€Z /x seuoqtues Z/T T NMOG +/ 
‘Sz /x seu0jtues Z@ NMOd »/ 
‘g9z /* seuojyues Z/T Z NMOC +/ 
‘T8z /x seuvoqtues € NMOG »/ 
‘862 /x seuoqtues Z/T € NMOC »/ 
‘OTE /+ seuoqtTues y NMOG «/ 
‘vEE /+ seuozyues 7/T b NMOC +/ 
‘ySE /x seuozyues S NMod +/ 
‘SLE /= seuojtues Z/T G NMOd x/ 
‘B6E /x seu0Qtues 9 NMOd +/ 


}=[4ZIS STAVE SNWEL]oTqes votyTsodsuesz, 


(24 QOOsT = e3ex buyumsse) potzea ebyuy eyL Qooy ey OF BOFQeTSET uF Yortd 


“souoqtues 9 -/+ seaem eyQ osodsuezy 07 seTzqUS 
ySnoue Sutupequod eTqey e& st ETEH “ZY OOOST = S3FY OF WEY pue ‘esed eYQ ST 
STq2 3eq3 CUMsse 5,307 ‘“pepesu oq PTNOM eTqey euo ATuo ueyQ ‘oures 9yQ eq OF 

poueddey eTTF O43 UF sOqEY CYR TIS FI “STTS ANWS S43 UT SC7eY INAMAATIG AUAAA 
ZOJ eTQeR e pee nok 3eyR ST POyAew sTYZ FO Yoeqmerp ey, “euoqyues Azeae z0z 
peqetnotes Apeezre spotred Tenqoe eyQ suTequoD yey, eTqeQ esodsuery e QonzqsuOCD 
03 ST poyjeu z0Q30eq Y ‘ouT3-TeeZ UT punos BSuTyAnd3yno rox TeoTWoOerduy pue 
SHutumsuos ewmty eq ued yoTyM yeu quTod Hut jects seaToaut styq ‘ATsnojzaqo 





LLT :spuoces 
-orpyu ut pessezdxe pue pepunoz st At ‘eDdTAEd OCTpnY ey 3 O73 AT pues Of pue 


TISTLLTOOO” = S9E6LZ"/ (989TT’90202/T) 
tezogzezeyy st ebtuy eyQ z0z potxed Hut tdues oust 
24 989TT°90Z02 = BPOZ9S7ZT°T * O008T 


rst eqez yoeqheTd eyQA uweyR ‘euogjtues T an 
eaem 043 AeTd 09 ystm nod pue ‘ZY OOOST ST SIFU S,CAEM OYA FF ‘OTduexe 0g 









z seuojtues 9 ao 
SZ98VLLEB°T seucjtues Z/T G 4n 
9EVLELTSL’T sou0jTues S an 
O€B8ZELTSO'T seu0jtTwes Z/T Pp ao 
ZSOTOPLES “T seucjtues v ao 
LLOLOESEP T seuojtues Z/T € an 
ZOSETSUTY T seuojtues € an 
YS86CSrEE T seuojtwes Z/T Z ao 
OSOTZ66SZ°T seuozTues z a 
STTLOZ68T°T seucqtues Z/IT T dn 
svpozeseeTt Tt seu0jTues t ao 
VE0E9VESO T eucjtues z/E an 

/«* Yard s,ejouj{007 »4/ o°T HOLId TYWNISTUO 
ZTEVLBEPE “O euojtues z/T NMOG 
8TLB868068 "0 seucjqtues T NMoad 
STP968098 "0 seucjtues Z/T T 
97SOOLE6L“O seu0jtues Zz 
BSESESTEPL'O seuoqtues Z/T Z 
TEL9OTLOL*O seuojtTues € 
LZ66TYLI9°O seuoqtues Z/T € 
$7S096629°0 seu0j tues v 
LSSEO9PES"O seuoqtues Z/T 
PVZOTEZTOS “O seuojtues S 
LYSTELEZS"O seuoqtwes Z/T ¢ 

s°o souojtues 9 





Rood EY} OF UOTRETET UT YOITad 






qunouwe sty Aq eqeu ATdTITOW 


90P'dINVS 


; “yoqtd s,eaem oyQ esodsuez3 of 
zepzo ut eer Suttdues oy Aq petTdtartnu eq 03 peeu prnom rojDeF QeYM smoys 
3eq3 eTqeR © st ezeH *(eTeOs pezedueq-Tenbe ‘uxeqjsem e Gutumsse) Zz Jo W0or 
UIZT SYR FO ToOQoeZ e Aq st Qunowe yes styR ‘AxeU SYA OF SUOQTUeS OO WoT, 
*qunoure jes e Xq pezemoT xo pester eq qsnu eqez yoeqhetd sqrt ‘ (seuojtues 
-/+) ‘seqou Teotsnu so ehuez e reao yoeqKkeTd 03 eaemM & MOTTE 073 TepzO UL 


“uoTatpuop dn- jes TeTAyTUT xO ATNesep 
e ATuo st STTF aNYS EYR UT pez0js epoMAeTA EYL “TITM 3e epowAeTE eyZ obueyo 
03 Zesn SY MOTTE pTnoys uofTyjeottdde ue ‘ostyw “eTTS aNWS ueatTh e uo qDezzO 
euos eAeY TITM seponmteta p TTS 3eyR sezansut styL *(e3Aq AsrzTF SYQ se ONTeA oues 
ey 023 yes ATeqezeqTTSep st At JT weae) TTOEM se Tequmu eAeM peUTZep e eq PTRoYsS 
eykq deyketa puooes eyy ‘T < sueyosoumn eyR JI “seqkq dewketa eyy Jo 3s2TF 

e432 eq pTnoys ejou TpTu e Aq yoeq peAeTd eq 02 # SAeM QueQZOduT Asou eUL 


*(epezy 3FOT 029 3YHTu ET) UOTQDeZTpP CeTeAS eYA esTEAeT 

ues uopqeottdde eyq ‘osty “eqez eyQ yes prnoys wexhord 
uofTqeottdde eyy (eaem oures oYyQ OT) ‘oures 9YQ |ze srEqumU 
SARM OYA USYM VATROEFFO Qsou st STUL “PTETF Cereqs eyA 
ut aybty of AzFET woryZ ,,SsOTD, SOCARM SOYA AeYQ ST AOeEZzZO 
qou ey, “TeAeT TETATUT S,T# eAEM OF OSTI pue SUMTOA 

0 38 42BQ5 prTnoys Z eAeEM ‘OQeT Owes OY AW “0 OF Epes 
pue (AQTOOTSA FpTu) SUMTOA TeTATUT SAT Qe ATeQS PTNoys 

[T SARM FO OuUMTOA BYR WeY4R Ydeoxe OFUTLS SXTT snl st styL 


*pezoubt exe szequmu eaeM ZERO SY 

‘(py zo Z Teuueyo) yoeref aqbta eq andqno eq 03 st af ‘(seqXq 

depketa e432 FO puodes oy) TequMU SeAEM puUOCDesS © ST OT9YR 

JT pue (¢ XO T Teuueyo) yoel oezegs AyeT eyQA Fo yndqno 

eq 03 st (seqkiq deydeta eyy JO 3SITF) # SCAEM ASITZ UL omaaLs 
*Teuuweyo 
e ,Tee3s,, 02 TeYReEYM epToep ued uoTQecTTdde eyqQ ‘AeTd 
Uy eTe sTeuueYyS ANOJ [Te JI “pezouby eze szequmu eaem 
xeyRO ey, “Teuueyo oexz Aue uo andyno eq 09 st ej0u TpTu 
e zoz (seqkq dewketa eq JO Asrts) # SCAEM QsSITZ SUL 


*steuueyo Auew jeyq osn ATuo ueq3 ‘Pp > STF sUeYOFOUMN SYR JI 
“Kyeatqoedsez ¢ pue ‘z ‘tT ‘O sTeuueyo ofpne ebyuy 
uo 3nd3no eq 03 exe ej0u TpTu e Tox s}# eaeM OUL - (0) LNWONSdSONI 


isedXq oepoydeta 
€ Nwd outzepy 
z OFMALS SUTFOPH 
T ILTAW SuTzTEpF 
O LNWONAdAaGNI SuTyep# 


+ ABTa OF CAEM ON, sUBeU QO FO O7Aq dewkeTA & WeYQ rSequeUSY 
*peqerdzequt eq 03 eze dewkeTa eyq ut seqiq eyR Moy setstoeds epowAeta 


SQOWAWId FHL SNILIIUILNI 


90P'dINVS 





FORM and Chunk Registry 475 


IFF Specification 


“Kytuwez 3ey3 utTyaTM edAQ azetTnoTqzed eyQ seqtzosep etqqtu ySty ey3 


out SsTYR We peuTyepun st dg ‘HINAS = @ ‘7LOGIda 
‘TLOgdda = D ‘TWANXD = a ‘zSswud = Ww ‘TSSWua = 6 ‘INOISSNOWGd = 8 ‘Z7NOUNd 
‘THnud = 9 ‘SOIOA = S ‘AWLIND = y ‘qawoaxai = € ‘CNIMGOOM = Z ‘ONIULS 


IsmoTTos se ,ATtuez, Jueumzysut ey Hbutqueserdez 

s3Tq p MOT OYA YITM (szeumrexbord 5 nok rox SAtq ¥) SeTAqTU Z OAT pepTATp 

st e3fq edX3 ey, ‘eueu peztsep ey} putz 3,ueo AT FF Queumzysut Jo ,edkq,, 
qoezz0> ey3 xox yorRes ueo zeAeTd sons oya ‘Aem sty ul ‘st Queumazqsut 

aya eqs ATQoexe zeAeTd snWS UE TT93 TTTM YOTYM epod OTreumU e eq 03 QUeOSUI ST 
xepeeyeaem yore ut e3Mq edAysul ey, ‘squeunzyjsut peztsep ey exTT BSutyjou eze 
eseyy FT weve squoUMIASUT ,,ATNeFOp, OF Arosez szekeTd sows Auew ‘uoseez styy 
z0qg ‘Queuwecetdez etqeqtns e xox yorees 03 Hutumsuod-owt A pue arnoTsstp Area 
S¥ 34 weyQ ‘punoz eq 4,ueD oweU QDexe ey JT 3nq ‘(shutrys Hutzeduod) mots 
sty st Atuo jon ‘oureu Aq squoumazqsut utTeqze> roy yorees sxeAetd sows Auew 


SeerssssssssssSssssss===== FdAL LNAINOULSNI FHL == 


*butdoolt ,sseTuees, eptaozd pue qndqno ofpne eyQ uo estou 

SAeUTWTTS TIT sty Tiw “Tenbe Ateqewtxorzdde ‘uot joes HBbutdoolt eyQ Jo pue eyQ 
pue ‘Hbutdoot ey3 Fo BSutuutbeq syA ‘Joyseuo eyA Fo pus eyy Fo sedots ey deoxy 
03 Axq ‘ATTeuta “uotqzod Hurdoot eyy Fo setduwes ysetT pue AsITF SYR FO oenzQ 
ST owes oyL * (squtTod ozez zo) ‘Tenbe Ateqeutxordde eq ptnoys uotazod butdoot 
ey Fo eTdures Asztz eyR pue uotazod yoysgeuo eyQ Jo eTdues yseT ayy, “or0ez 

JO ONTeA & YRATM eTdures e uO 9q PTNOYS eAeM OYA FO ATeAS SYA ‘UCTITppe UL 


*yoeqhetd eyq zo Butfuutbeq 

ey. 3e syOTTS pue sdod ejeutwtte TTT stuL °(qutod butssoz> ozez e) orez 

yO enTea eTdues e& 03 squtod ssezppe BHutyrnsex eyQ ‘qutod yjzeqs eTdures eyQ 03 
peppe eze Key ueym 3eyQ Os sjeszzo oyR jes sXkemtTy “eaeM CYA UTYATM TeYAeboq 
esoto ATeaTReTET Eq TITM senTeA eseyQ ‘eotqoerd ur “eaeM 9yQ FO uoTRZI0d 
YORRVS TeTATUT syq utyqtm nok deeyx TITM 3eYQ sgjeszzo Hbuysooyo Axzq ‘x0qTpe 
ptydezb e Butsn eze nod sr ‘szequnu HSutseezouy eq prnoys sentea juenbesqns eyL 
*(eqep eyq go BHbutuutbeq eyA wory yoreq Aetd of zepxo ut) oxez oF Aes eq pTNoOYsS 
Loletaenten ‘3eszzO ysArtZ CHL © (UOTQIOd HutTdooT eyQ UT Jou eT) eTdures eyQ 

JO uoftzzod joyseuo eyy UTYATM eq PpTNOYs eTqey AQToOoTea SYA UT seTIQUeE OT SUL 


STIGWL ALIOOTZA FHL ONINWW 


‘ezempzey ebjtuy ey Jo ebuez Fo Ano ere eTqeQ eyR UT spotzed ey 
JT yooyo AeyA op AON ‘eTqeqZ esodsuezyA ayQ UT seTIQUe Fo Tequmu ey puockeq 
ST Qunoue esodsuezy ey JT Ces 09 YOoYS 4,uOp seTdurexe osoy A WeYQ SION 


M° 9Aou 
T eppe 
@aomM & YOReZ OQ TEpITO ut Z x! op‘op T°ppe 
SNOT peubts e 3T exeu! op = T'3xe 

op «4° 4x8 

op ‘e30NR;00% 8=gq'qns 

OP ‘TOCUMNSIONTPTW dq" eAour 
OF ‘HOLId TWNISIUO eet 


op‘ (oe) 
oF ‘op 


(qaom) potzeg ebtuy ey Q/ 


@qou 3Ooor s,eAReM 9YQ QOeIQQNS!: 
zequmu ej0U peATedez ey y!: 


66 Mop 
SOT MOP 
ett Mop 
8TT Mop 
S2T Mop 
‘ehuez Fo Ano AtTTenyQoe eze 
HutMoTTos eyy ‘LZT = potzed ebtuy umutuyu eyQ eouts 


290P'dINVS 


€€T MOP 
Trt MOP 
8pT MOP 
“4st "Op 
L9T M°Op 
LLT M°OP 
est MOP _ 

youtd s,ejoujoor : “Op HOLId IWNISTUO 
TT Mop 
€2Z MOP 
9€% MOP 
Taz MOP 
g9Z MOP 
T8sz MOP 
86c MOP 
9Te Mop 
vee Mop 
pSe Mop 
SLE MOP 
86—€ MOP eTqeL 


eq pTnom aTdurexe eaoge pue Areyo osodsuezy zyooosTt eu ‘ATquesse ul 


potzeqebhtue 


/[qunouyesodsuez3 + HOLId TYNISIUO] eTqeq uoTyzTsodsuezy 
qunouyesodsuez3 


/* DNOT GINSIS & 3T exeW x/ / (EQONQOOT - TEQUMNEIONTPTH) (SNOT) 


/» (uotqeoTTdde ey3 yRTM ebueyo ueo sty et ‘otureudp) 
eTqez uoTyATsodsuezy oyy UT sejyzque Jo Tequmu Sy ST AZIS AIAVL SNWUL »/ 
T + 2/3ZIS TIAL SNWUL HOLId TWNISIUO SuTszep# 


/* (0% ®79Y) Tequmu s,9}0U TpTW PeATeDeT SYA ST TECUMNSIONTPTN x/ 


1D UT ,QzeYyo esodsuez3, zZYOOOST eAcge oyQ Hutsn pezetntTes st potred 
buttdues ebtuy ey moy st STeH “BE = SIONQOOCY SYR pue ‘OOOST = O7ea 

eYy3 3eYQ TeAcCoOSTp em ‘ezngqonzA4s s8,¢ eaeM Hututuexe uodpn “¢ requmu eaeM 
Ketd 03 305 st op# eqou Tptw (dewAeTa ey 03 Bbutpzoope) ey oumsse 5, 30T 


66 /* seuoqtues 9 
‘SOT /x seuoqtues Z/T S 
‘ett /» seuojtues ¢ 
‘SIT /x seuogtwes Z/T ¥ 
‘S@T /» seuo tues v 

/+ "e6uez zo 3no ATTenqoe ere 

HutMoTToy eyR LZT = potzed ebtuy wunututu eyy 

‘CET seuojtues 7/T 

‘LoL souo tues 

‘SPT seuoqtues Z/T 

‘LST souoqtues 

‘LOT souoqtues 

‘LLT souoqtues 

‘L8T suo {tues 


20P'dINVS 





Devices 


476 ROM Kernel Reference Manual. 


*Bbutuued pue Bbut{tdures coezeqjs exTT sepou yxoeqKetd 

snoTzea pue ‘seqjez BbutTdues oqerzedes ‘etdues yore rox sedoTeaue pue reRqTTF 
eqezedes ‘q2e93s eTdues AQTOoTeA :eze seaznqeey yons “szeTdues oTsnu TeuoTssez 
-ozd 03 eoetduoumio> ere 3eYQ semnqeez 10x eQep Hbutr0As MOTTE Jou seop XASB 
‘uoTssTusuezq eRep TeoTsnu FO prepueys ORF Op SYR ST YOTYM IGIW sezoubyT xase 


*zeuueuw sty AtTQoexe ut yoeqheTd eyA yoquerAs 03 peubtsep st euros 

XASB SUL “29e ‘edoTeaue epnazttdue s,jueumzysut eyQ ‘sestou eatTssnored/puym 
4@INQONTAS SUo_RTEAS SYA se sQueWeTeS Yyons oj shutyQ (TeoTsnuun XYA pue) 
enbse 7075 seop ebuez eaeq00 eztque ue zeAo Ano eTdues e Bbutyojezqs ‘osty 


-ebuez ejou TeoTsnu sgt eVeeTD 03 eAeM ETbuts e Fo suoTWeTOd 

-zequUy sesn (uehbz0 oTUOTADEeTS ue WoOIZ eptTse) EeodUeQSTXS UT SUOU se ‘QueUMI45 
-Ut TeoTsnu e eonpozdexr ATTeoTAsT Teer O73 EeTqTssoduy AT seYeU euCTe uoseex 
Azea stu ° (eHuex Teotsnu s3z ynoySnozyy yjueumzgsut Aue jo seytdues jueressTp 
‘Tezeaos HutztTt4n) H5uttdwes-tytnu esn 03 eTqtssoduy ATreeu st AF ‘TTe FO 
asazta ‘Suttdwes otsnu Teuotssesord zoz eqenbepe jou st xass ‘TTeysgnu e& ur 


(,eXemAue xases yatm Buozm s,3eqM,, 20) 


‘pqe /,TeTbrnp, peuweu eq prnoys eTTF 
uoFAenuTquoD yAsatsZ eyQA ’,eTHznD, PETITES ETTF & peses zesn e& ZT ‘eTduexe Toa 


*zepzo zedozd ey3 ut seTTs ey peotez ues wexbord e ‘Kem sty ul “ut st STTF 
e43 TeaeTqns AeYM e7eoTpUT 0O9 SUeU SYA OF pepuedde zequmu TTose ue eaeYy soTTF 
quenbesqns ‘zepun saes 03 Ssoyo ZEsN SYA WeYQ SueU EYQ sey STTF ,, WOOT, SUL 


:butMoTTos 
9U2 BT poyjeu ey, ‘pe_zeTezr eq pTNoys seureueTTF eyR ‘eTNAeeF voTRenuT QUOD eY4y 
Bbutsen setddoty ueemjeq eTTZ aWuS eB 3atids 03 Azesseoeu sewooeq AT wEeYyM TO" 


messssss========= SNOIINSANOD ANUNG TIA ================= 
“4seT eq ysnuU 
MUNGO AGOM SUL “TTS 3& STTF oyQ ut zeedde peeu eseyR Jo euow yHhnoyQ ‘repro 
Aue ut mottos Aeu sxunyo AWWN pue Hinw ‘(>) ‘ONNY S49 ‘STU zeRIFW “XUNYS 
UGHN eq Aq peMoTTOF ‘TTS eyQ UT asrTZ eq Asnu ATsnoTaqo Tepeey dNWS SUL 
SYNNHD 3HL JO WACHO AHL 
‘queumz3sut ,,NMONDINOA, sueeu sty wey ‘0 st eqiq edAR s,oneM © ZT 
“WOUd TAWNS © eq PTNoOmM styQ ‘9zxO sem e7hiq edAQA s,0AeM © FT ETdUexe XOZ ‘os 
GSION = 9 ‘SNIS = G ‘STONWIUL = b ‘HLOOIMYS = € ‘mavnds = Z ‘SONTULS = T 
IsMOTTOS se st eTqqtu yhty ey ‘ATywey HINAS S43 70" 
@OTO YO LYG ISNIWOW TIwa = 4d 
‘“TIwd ONIONNOG = A ‘SONWIWAY = d ‘HSWIO quoms = 0 ‘Wwados = a ‘SaMOUD 
ONTUVOU = W ‘aSowldaw = 6 ‘SOOM GMOWD = 8 ‘CNIM = L ‘NWHOO = 9 ‘A TLSIHM 
ivod = ¢ ‘IMOUS 50d = & ‘Wawa 90d = € ‘SNOHdATaL = 2 ‘NOS ANIHOW = T 
remMOTTOF se st eTqqtu ybty eyy ‘Atyuwes ZsLOgdsa S43 204 
; aaLSLood 
= 4 ‘SGSION JTONOC = g ‘squad = d ‘NIWG = O ‘WHONNHL = @ ‘SSWID NaNOUE 
= ¥ ‘WRLdOOOTSH = 6 ‘UETIadOUd = 6 ‘ENIONG Lac = L ‘NnDgOWdS = 9 ‘ESOT 
aood = § ‘WwIs wood = » ‘N3dO wood ONIMWHNO = € ‘LOHSNND = @ ‘NOISOTdXA = T 


ISMOTTOS se st otTaqqtu ySty eyq ‘ATTwesy TSsLOGIAA SYR TOT 


90P'dINVS 


@ILSIHM = L ‘HONWI = 9 ‘AHLWaUd 
ZIWWad = § ‘000 FIVWEd = ¥ ‘000 BIVW = € ‘HHW GIWWad = @ ‘HHW @IWW = T 


rsmoTTOS se st eTqqtu ySty eyq ‘ATywez AOIOA CUZ T0Og 
(¥2NTa sseq - SONTULS ey UT punoZ sf sseq pexotd oTAsNoDe ue 3eYR SION) 
NIIOONYW = & ‘UWLIS = 2 ‘SSWA GaddoOd = d ‘SSVH GaddWIs = 0 ‘ssvad “oOsTa 
‘OCNWa = W ‘WOULS GYOHD = 6 ‘SOINOWYWH = 8 ‘CUOHD UEMOd = L ‘ONTULS NOTAN 
‘ONTULS-ZT = G ‘OILSNOOW = F ‘GHLYOLSIG = € ‘OTMLOITE ASLAN = Z ‘OTULOETE 
ISMOTTOZ se st eTqqTu ySty eqg ‘ATTwes UVLIND e143 


TIOU ‘IWEWAD = W ‘3RaL TIZG = 6 ‘ONOD = 8 ‘HSWUYO FNOHO = L ‘HSWUO 
‘“TWANAOD TIA = G ‘SCIU = » ‘LWHIH dals = € ‘LWHIH NadO = @ ‘LWHIH dasoro 


ISMOTTOZ se st eTqqtu ySty eqq ‘ATyuwez TWaWAD S43 TO" 
TIS4SNIMOOTD = 9 
‘STTRG UWInENL = @ ‘SNOHAOTAX = W ‘WEWIUWN = 6 ‘S3GIA = 8 ‘TITRE = L ‘SYOWUWN 
= 9 ‘SILSIHM = ¢ ‘SNTUNOGNVL = » ‘HIONWIUL = € ‘TTIZEMOD = z ‘MOOTE = T 
ISMOTTOF se st eTqqTu ybty eyR ‘ATTueZ TNOISSNOUad 249 TO" 
woud SOT = € ‘TIOW INVdWIL = Z ‘INWAWIL = T 
ISMOTTOZ SB ST ETQqTU YSty eyQ ‘ATTuweFZ ZWNYA SUR TO" 
WOL B1gnod = 4 ‘Whd TEaLS = J ‘OONOM = a ‘MOILS ssoud 
‘LOHSWIU = @ ‘NOL OBTT = W ‘MOIM OTE = 6 ‘TAUNS OBTE = 8 ‘TUYNS HSNUG 
‘WIS WONOD = 9 ‘LIH WDNOD = S ‘SHIWEWIL = » ‘WOL = € ‘HUWNS = Z ‘HOIM 
ISMOTTOZ SB ST ETQqTU YSty eyQ ‘ATTWeF TWNUC SYR TO" 
aan = ¥ ‘NWOUO 
WSIGaVd = 6 ‘€-@ GNOWNWH = 8 ‘NWDUO AdId = 4 ‘LENIAWIO = 9 ‘CUOHOISaUWH 
= ¢ ‘ONVId XOL = ) ‘ONWId MNOLAMNOH = € ‘ONWId “OdTH = Z ‘ONWId GNWHD = T 
rsmoTTOS se st etqqtu yhty ey ‘ATTurey GUWOMATN OUR TOg 


WOINOWEWH = 6 ‘LANIUWIO ssva = 8 ‘NOOSSWH = L 
‘aaqgoomd = 9 ‘OTODDId = ¢ ‘SOdO = » ‘HINTA NVM = € ‘HINT = @ ‘LENIUWIO = T 


ISMOTTOF se st eTQqTu ySty eyg ‘ATTwez GNIMGOOM 943 704d 

NOH HSI'TIONS = ) ‘NYOH TWONTE = € ‘WaOL = 2 ‘NYOH HONGUA = T 

IsmOTTOZ se st eTaqqtu ySty eyy ‘ATTwezy Zsswud eu Tod 

@LOW JNOGNOUL 

= 9 ‘SQIIS ANOGWOUL = A ‘SNOGNOUL = O ‘dOUd LAdNNUL = a ‘LAANNUL AILAW 

= W ‘LIGNNUL = 6 “IMOYD ONWadOS = 8 ‘XWS ONWUdOS = L ‘IMOUD OLTY = 9 ‘XWS 
OLTW = ¢ ‘IMOUD YONTL = » ‘XWS MUONAL = € ‘IMOUD Tuva = Z ‘XWS SNOLIUWa = T 
iSMOTTOZ se SF eTqqTu yYSty eyQ ‘ATTwesz Isswid eu Od 

WHAL ssva = a ‘(sseq zzeC) wonTd ssva 

= @ ‘MO® SSWH = d ‘WEYL OTIED = O ‘SITS OTTED = @ ‘NONTd OTTEO = W ‘Mod 
OTTHOD = 6 ‘WHUL WIOIA = 8 ‘SITS WIOIA = L ‘MONTd WIOIA = 9 ‘MO@ WIOIA = SG 
‘OTONGUL NI'IOIA = & ‘OGNWSSI'ID NI'TIOIA = € ‘MONTd NITIOIA = Z ‘MOM NITOIA = T 


ISMOTTOF se st otTaqtu ySty eyq ‘Attwesy ONTIULS ey T0g 


90P'dINVS 





FORM and Chunk Registry 477 


IFF Specification 


*<BQep> <eztTs-eyjep> <dI> ‘:eangonazys JAI pxrepuegs eyqQ YTM 
‘uyebe ‘,,syunyo-qns-qns, yo dn opeu ore syunqo-qns uLxga pue 
Osad ey, ‘“eQep ou pue -- ezts ozez eaey syUNYo-qns radoL SUL 


“(®TTF .Teuze xe, 

ewes e432 ut pezoqs eze AeyQ sseTun uverzpTTyo eaey Qouued 3o0efqgo 
TeuzrejzxS ue 4eYQ sUeOCU STULL) “peeqsuyT USRzITAM ST yUNYo ULxE we 
anq ‘pewzogzed jou eze (¢ 03 (T sdeqs ‘sqo0efqo ,Teuzeyxe, r0g 


‘uezpTTYyo eyq FO pue eyQ Hbuyyzrew ‘ueqqyzim st yunyO rgoL WwW (€ 
“PTFYS youre roz 

peurogzed eze (¢€ 03 (T sdeqs ‘uexpTtTyS sey at SI (Zz 

*qoefqo sat BbuyqTrzosep ‘ueq3tIM st yuUNYD Osada YY (T 


‘ASTI pexutT Atqnop e Fo epou yors zoz 


ISMOTTOZ se peqjzoddns 
st Ayoxrertey Auepusosep syL ‘“squepueosep sqt TTe 43M Buote 
‘yunyo cqo eqezedes e ut ueQQTIM st szeqj0I7q ,peey, ey JO Yyoreg 


*(quezed sqt 

03 xzequtod ,yOeq, e& sey epou yore ‘uOoTATppe ur) ‘uo os pue ‘sqsTT 
.USIPTTYopuerb,, ey og qutod uezpTTYyo euL “ISTT uwPTTYS. pexuTT ATqnop 
eB 03 xzequtod (TIAN Atqtssoed) e sey spou yore pue ‘AsTT peYUTT 

Atqnop e ut qdex exe sepou zeyj02q eYL “uO Os pue ‘uezpTTYyopuerb 
eaey Aew vsezprttyo ey, “s30efqo prtyo eaey Aew zeyj017q yorg 
“szeyj0ezq (4sTxes) S37 pue ‘A0efqo peey e& st exeyL “SMOTTOF se st 
Ayoreztey 3oefqo ayQ Fo ernQonzAs ey ‘ouTHbeml pue rSeATTS oqizny ur 


‘ated cqoL/osad & 03 QueTeatnbe st yuNYS ULXT 

ue puy ‘“yunyo cgoL B5utpuodsezz0oD e eq Asnu ezey3 ‘yUNYSD Osada 
yore zoq ‘utTeyo Ayorerztey e Fo pue eyQ Hutyzew yunyo cgoL e& pue 
‘Kyoreztey e Fo epou suo HutqyTzosep ‘yunYo Osad e /eTTs eyeredes 
e ut qoefqo ,Teuzeqxe, ue Butqtzosep ‘yunYo YLXZ we :sXuUNYyS-qns 
Lao Fo sed&ky ¢ ore ezeyQ ‘ATQuezinDd -yerdzequt of 3ATNOTZITpP ezou 
Atayqt1s eze pue ‘setyozeztey yoefqo yxoddns ,sxXunyo-qns, rao eU™uL 


*qexdzequt o9 premzosaqybterzys ATeaTQeTeT ere ,sXUNYO-qns, OANI SUL 


*<eQep> <ezts-eAep> <qI> :emNQONTAS BAI prepueqs ey 
UATM sxUNYS FeTTeEus Fo dn epeu oxze ‘uzny ut ‘sxuNYS CGO pue OANI eUL 


(4 £40. = GIy> -- eoeds e Aq pemoTTOZ st CHO :990N) “syUNYSD CEO 
JO xequmu euos Aq pemoTTos yuNYoO OANI (TeuoTydo) ue sey WOU SUL 


“S®TTS .qeCqo, PUe SETTZ wTTS,. 

yqoq ut szeedde yunyo rao SYQ puUe ‘SOETTF wTTSS, S,TeATTS oqing 

uy ATuo szeedde yunyo ogNI CYL ‘“Ayorertey j0efqo ue Hutqtzosep 
yunyD cgo ue pue /eqep rzeazesqo Bbuyqyzosep yuNnYo OFNI ue :sedAq 
yunyo oma ATuo sey dadL WuOd & ‘suTe} gar pzepueqs, ut ‘ATquezznD 


‘eqep qoefqo seqtTim/speez 3} uEeymM 
dqgL Wiod pepexzhdn ue sesn ‘,eutbewl, ‘Xosseoons s ,TEATTS Oqiny 


‘eqep zeazesqo (AT Teuotydo) pue yoeLqo 


uye_UOD SEeTTF EYL *,UOTIdTIOsep ejep de, TOF spueys dadL ~‘e3ep 
butzepuez qe OF O°€ TEATTS oqany s,estndwy Aq pesn st aadL WYO 


qddqL wiod 


(estndul) zeaTTs oqazny, ‘eqep HButzepuez q-¢ 


90p'qqddl 


*syoetT ebjuyw eyQ pue ‘AQseoq mou seuTyoeu reyQo sy AeYR 
ustTeuotsseszoid Jo TeAeT eyQ uTeAQAe Of ereMAzJOS ebtuy TOJ eTqtssod 31 eyeu 
Tits AzezqtT O/I ASTtP ANWS 943 UAT ‘qeurozy styq ‘AT[nzodoy ‘ebtuy ey oz 

Butttes suotjeottdde ATuo eyA ere sexoqpeerq oepta pue ‘szeqqezrb-ouerz 
‘syooTueh ‘suwezbozd uotqeutue pue quted eyq exoyeq szezzo ebtuy ey setq 
-Titqedes zeacqeym AToTdxe 03 azeMQzoOs OTsnu AOZ QueQroduTt st AI *,,reqnduoD 
oepta e, se ebtuy ayy buttoy-uoeftd eze szedojtenep ebftuy Aqaed prz¢g pe ydts 
-qzoys jo doz quezznod eyQ pue ezopoumiop yj0q “320ddns erempzey pue eremqjos 
oTsnu yRoq uT szeqnduod Js TzeqW pue ‘YysoqUTOeW ‘SeUOTS WAI putTYyeq rez sheT 
ebhtuy eyy 3eYQ sueToOTsnu Teuotssezorzd Hhunowe ehpetmouyx uoumiod mou ST AI 
-suerboizd Butzoos pue ‘szojtpe yoqed ‘szeouenbes go Aqetzea e Hutsn pue HutAng 
@ze s,UBTOTSNU ‘IGIW JO AUSUTYSTTQeAse WITZ SYR UATM *‘szeqnduos HutAnq oeze 
s,1etTotTsnu Teuotssezord assneoseg gQeuTOZ AWWS e439 peeu ebtuy eyW sevop Aym os 


seTzes XL WHWAWA 

xdqd & ,WIZHYAdO 

T-Z4 s,OISWO 

FOVWaIN s ,OINOSNG 

Obp OIGNLS ‘000% LaHdOud S,LINOUIO TWILNandas 
MOLWIONA ‘XWWa Ss .0Wa 


rsqonpoad Teotsnu HbutTmMoTTosy eyA FO seTat Ttqedes eyA Aq peaztdsut sem euros 
@YL “eTBMAZOS uT semnzeEezZ TeUOCTSssezozd sseyQ sejetnutTs AeyQ wexzhord e Aq pesn 
eq ued ZeYQ AeEwIOFZ e YRTM sueTgord sseyy zo [Te Apeuwer oj sqdueqjze aNVS 


90P'dINVS 





Devices 


478 ROM Kernel Reference Manual 


peazesez/pesnun 

‘epaznos aybtT TeotTuoD 
‘epanos 4yqftT Teotazput TAD 
eoanos 3ySTT Teotzeyds 
[b-€ SAT 


ayStT Butpqseo-mopeys - pF 
aqityt B5utqseo-mopeys-uou - °o 
2% sata 


peazeser/pesnun 

‘epueqstp Yat FFO STTeF Aqysuequy - duet e exTT 
qybtTuns exTT 

duretT © jou 

iT-0 sata 


ISPTSETS 37q Tereaes Fo pesoduoo eze szequmu dueT 


oedXq duet Sutqeotput zequmu ‘dure'y qaom 
adXkq 30efqo BbuyAeotput xzequmu fedeus q@aomM 


y ezts - dWHS 
‘pge ‘syqed Azoqs Butkztoeds ‘butyoer3 exoured Foz pesn 
*qpvefqo eyqQ xox eueu e ?: ‘(8 T] ewen aLAq 


8T ezts - AAYN 


syunyo-qns-qns Osada 


yqed uo quezed MoTToxy wezpTtyo OoOTxO GN MOTIOI 

(pesn jou) 00v0x0 NOITY_Z 

uotqoeztp s,yqed o3 stxe x ubtTe 00z0x0 NOITY_X% 

(pesn 30u) 00TOxO NOLI¥ X 

seqeutzrooD TeDvotT ut HSutrteos 0v00x0 TOs_OOT 

SOREUTIOOD TBoOOT ut woFjze jor 0700x0 LOd_DoT 

(pesn jou) seqeutTzrOOD TeDOCT UT eVeTsSUeTR OTOOx0 WAL_OOT 
saqeutI0c0S ptz0m ut ButTeos vO000X0 Tos_saw 

SOQEUTIOOD PTIOM UF woTFWe Vor 20000 Lou_say 

(pesn jou) seqeuTr0OD pTIOM UT eAeTsUeTQ To0ox0 Wan sav 


isbets atq FO younq e& st PIOM ,OFUT, SUL 

*szoqoez eTeos Z pue ‘x‘xX seTsDeds TORDeEA ETEDS SUL 

‘sexe Z pue ‘x ‘x 

243 ynoge seThue uotqejoz seTytToeds ,10Q0eA, ERe{0H SUL 
*pesn ATQuezznD jou st TOROSEA SAeTSUeITL SUL 

"“go0zrez OF 308 Oo 

PTnoys prets [J]yyea eyR yRed ou sft ereyR JI “uot Qewyue eyy 
yO owezz yore ut eoueAsTp Tenbe ue seaow sXemTe yoefqo ey3 
3eq3 Os peqetodzeqjut st yjed eq, ~“queqroduy st butzepz0 
ebpe ey, ‘“ebpe yset ey Fo qutod yseq{ eyQ 03 ‘ebpe 3szTz 
ey3 FO Autod 3sz2Tz ey wWoTy seacu AOeLqo eyL ‘“sebpe yATM 
peqoeuros squtfod jo eouenbes e eq prnoys joefqo yyed ey 
“eQep TTe> eyQ ut ADefqo peuweu e of sxzezex oueu [Jy7ed SUL 


/* TeI0R seqkq 9G x/ ‘xaoLs { 
/« sezkq Z ‘ozuy asoMn 
se qhq 2T feTeos YOLOAA 
seq ZT feqe908 AOL 
seqkq ZT JeqeTsUeIL YOLOTA 
seqkq 8T ‘Cet]qaea aLAga 
} Azoqs Aonzqs sopedsq 


90p'qqddL 


(‘eutbeuwr Aq ueqqobzoz pue pezoubt st 31) ‘“eanqeez ,y Red 

e Hhuolte epnz4xe,, s,IOEATTS Oqan], TOF pesn osTe st 3 *ezeued 
eyQ 09 Zo qoefqo ue 09 peyoegqe eq ued AT ‘TTD eTbuts e wors 
STT2o peyeutue butyzezeueh ut pesn st ernqjonzys HutMo [ToS euL 


/* Teq703 se3{Xq 09 ‘waodn { 
/* ezTs - seqkq ZT ‘8 YOLOGA 
/» S¥xe zZ - seqkq ZT 72 UOLOAA 
/« stxe K - seqhq 2T ‘q YOLOGA 
/» STxe xX - se qkq ZT 7B MOLOGA 
/ wot3tsod seqkq ZT _ *2% WOLOGA 
} wxr0FQ AONzASs FepedAR 


/x Teq03 seqkq ‘XIULWN { 
/x seqhkq ‘a YOLOIA 
J» 8eqkq ‘f YOLOaA 
/x seqkq «/ ‘I YOLOBA 

} septzqeu jonz4s yepedAR 


/* Te seqkq ZT +/ ‘AOLOTA { 
/x s0qhq § «/ 'Z Lowad 
/» 8e2Kkq py x/ ‘kK Lowad 
/x s03hq y x/ X Lowag 

} sz0q00a jonz4s yopedky 


/x seakq € «/ ‘Celuotod agian sepedxy 
/* 8034q b x/ ‘mowed SNOT Fopeds3 


:MOTeq pesn eze s,zepedA3,, SuyMoTToy euL 


“STTE O43 ut eqhq oz0ez 

e Xq pepesezd eze se37kq qou € ey ‘seseD YONS UI “PIOMONOT 

e JO S,AST PZ SY OQUT PTSTF TFOTOD oy speor TeaTTS oqinL 
‘syunyo eqep eyy FO euos TO_Z ‘“enTq ueyR pue ‘ueerh Aq pemoTTos 
‘qasztz sXemte st ped ‘“ZoToD eyA Fo squeuoduos entTq pue ueexr5 
‘pez ey butjuesezdez sqLxzgn eezyR se pezoqjs sXemrte exe AoyL 
*eqep ey UT SsPTETZ (adu XO) TOTOD Tereaes ere sTsyYQ ‘puoDesS 


"mOTeq 5, LOWUd, SB peTTeo ere 

Qewzosy sty UT peTojs szeqUMN ‘ZOATTS Oqany; JO uoTszea ,TebequT, 
ey3 UT pesn QeUTOZ TeureQUT eYR st (ATTeNQDe) AT puy °QeuLTOS 

qutod Sutqeoty zetnotqzed Aue jo quepuedepuyt eq of eQep SYyQ SMOTTE 
STUL ‘“dAEPZEOQOOS (TeupoOepexey) se peo js st 6STPYT € zequmuU SqF 
‘etduexe ue se os ‘9¢gs9 Aq peptatp zequmu 3Tq-ZE eq Sst zequMU 
enz3 eyA 3eyR YOns ‘sxequmu ,TeUCTR0DeIZ ATG-zE, se pezojs eze AoyL 
‘pge ‘sxojo0ez BbutTTeos ‘sethue uopzeqoz ‘suotTatsod y0efqo butqTzosep 
‘eqep ey ut buyzeedde sptety TeoTxreumu Tereaes ere eTSYQ ‘3SITI 


“STTeIEP SYR YRTM UO ‘MON 


‘ezts weao ue AT eatTh 

03 e3hq e23xe eUO YQTM puSe eYyQ Ae pepped eq TITM PTETZ <eqep> 
Hutpuodpezzop ey3 ese yotym ut ‘zreedde Aeu <ezts-eqep> ppo ue 
3eYQ OTNI ZIT O43 AAMASAO TIIM 37 UOTITPpe UI ‘“dtys of sezkq 
Aueu moy soQeoyzpuy PTety <ezyts-ejep> ey, ~,syxunyo-qns-qns, IO 
,»syunyo-qns, pue -- syunyo peztubooez-un Aue zeao buyddtys 

JO eznpesord gar pxrepuezxs E43 MOTIOT TTIIM SreMQzZOS TEpeCy 


(“seTTS aGL Ut syunyo uLxa gzoddns jou seop eutheuy ‘ATquezznD 
‘setts .32efqo, GddL ut ATuo sTeep pue ‘seTTy TTS TeENPTATpUT 
yO eBept eyQ suopuege euTbewl “STTF TTSO Sy OF ,TeUTIAXS, 
ST 38U3 STTS e3ep ,70efqo, ue OF TeFyeT OF SETTF SIEP TTI, 
S3T © MOTTE 03 ZeATTS oqany Aq pesn erem sq0efgo , TeureAxd, ) 


90p'qqddL 





FORM and Chunk Registry 479 


IFF Specification 


-Kezze eyR ut uortqtsod zetyq, Aq 03 pexzezez 
eze eyZ ‘“sq0efqo woqjsnd az0z squtod ey3 TTe sey YuUnYo styL 


‘pesn st Sutddeu exznqxeQ squtod / f[]squtod woLogaA 
ueyM seTnpou e2n4xeq rozZ sxeQjeuezed Fo ASTT SYR ST STUL gunos qutod / /qunopa ss aquomn 
szejeuezed e1ngxeQ / ‘([9t]swezeq Lowid qunoo qutod » ZI + Z ezTs - SINd 
*sefpe pue squtod eyq TTe Sutmezp ueyR 
zeyjer umeIp st 3eY4Q pPTTos zeTnbueqoez e& Jo ezTs ey Jes OF pesn 
‘repro ees osTe exe syqbuet sexe ey ‘jes Getz ,MerpyOTHS, sat sey yoelqo 
ey2 03 spuodsezz0> Hutrzepzo eyL_ “yuNnYyS Gowda SYR uF Qunood eDe;z ey JI “TOATpPS ey UT UMeIp sexe SQEUTPIOOD eYQ Jo syQbueT eyy 
ey YyoReU pTnoys junoo ey, “sqoefqo woyjsnd ut eDey yore TOF aze Key ‘sqo0efqo woqsno zoqg ‘edeys yoefqo eyq uo butpuedep 
SAUSTOTFFOOO UCTssTusUeTA PUES UOTADeETJET ‘TOTOO sy ore SseyL skem zo AjeTzeA © UT pesN OTe seZTS SYL “SeAcqe YyUNYo dGWHS ees 


MoTeq TLXL ees - eutbewy Aq wezQTIM Jou - 79 EZTS - Uva 


sroTOO i[] szotoo -UoTOD SeZTS UAOLOGA 


‘ 
SIOTOD FO Qunod / i unos qaaomn 


ZI ezts - azZISs 
qunod » € + Z eZTS - ISIL 
qunoD » € + Z eZzTs - ISTY 
quno> 4» € + Z eZTS - ISTO 


‘zeTnotpuedized oq Asnu sz03DeA 9YQ pue 
‘(A 03 esoTD 20) euo Tenbe ysnu squeuoduoD z0RzAeA EYQ JO sereNnbs 
ey3 JO ums 9yR “eT - ,870Q0eA ATUN TeEUChoyAIO, eq ysnu Key, 


*squetotsze0o Aqyze{tnoeds pue ‘uegsks aqeutpir00s yoefqo eyR xOF sXTOQDSA UOTADeITp ere ssoyL 


uotsstusuez3 ‘uoT_ZDeTyerT pue ‘ToTOD g5y yoelgo uteu eq ere sseqL / 
‘STXWZ WOLOAA 


aoTOd SSTXWA UWOLOTA 


ZOTOO gu iToD 
WOLOAA 


ozez eq ysnu - o3hq ped iped aALAG isTxXWx 


ezTs - 9€ eZTS - SIX¥ 


vy OZTsS - 
py SZTsS - *zanaemoy ‘ofuez 
v 


ezts - 3ey3 eptsqno peoetd eq Aeu ezeures eyQ pue ‘seornos qySt 7 ‘ebuexz 
PZOT °3 PZOT- 243 UT sqDefgo sees Atuo z9eoer3-Aez eyQ ‘AT QuezanD 
‘stxe/qutod yqed qxeu ey3 02 qQed eyW “9€SG9/GESS9 PUE LOLZE 02 B9LZE- ebueT eYyA UT ee sejeUTpIOCD TebeT 

Huole eouejstp eyy st PTET EZTS XK SeYQ SeSTMIeENAO “uedo sueeu 
Oxez-uou ‘pesoToD suweu orezZ ‘jou TO pesoTo st yAed syQ reyQeEYyM -uotqtsod s, 30efqo ayqq / fUOTATSOd UWOLOGA 
STTCR qed ey4R uo AuTod AseT EYA FOF weRT ,OzTS Xy SUL “Yed eyR 
Huote jqutod yoee xox ezngqonzAs WNOUL & sutequoo Aexzze ejeda euL 


Atuo eupbeur - yp 


et ezts - Isod 


*sqoefqo ,yjed,, euthbewr rox ejep stTxe eyQ suTeQUOD YuNYO sTyL 


eqep stxe : ‘Cel({leseqa waoaL 


Atuo euphbewr - qunoo stxe 4 9 + Z EZTS - GHid 


*seTbuetz3 Aq peqoeuu0o. 
eze 7eYA szequmu oefpe zo setdtz3 st Aezze [¢€][]sqoeuuoDp ceuL 
“*sqo0efqo wogjsno rox astT (eoez) eTHuetzy eyA sutequoD yuNYoS sTYyL 


qunoo esez / fqunooL dayomn 


qunos eDey » 9 + Z BZTS - FOWI 


*Xexzze []sebpa eyq ut wopytsod 

zety3 Aq 03 pezesex eze sefpg ‘“sebpe ey 3 Aq peqoeuuod ere 
qeyQ szequnu jutod zo sated st Aezze [Zz] []sefpq eqs, 
*sqo0efqo woqjsno z0z AstT ehbpe eyQA suf Quod yuUNYO sTtyUL 


qunoo efpe / /qunoog aaomo 


qnoo ebpe » » + Pp EzTs - Fda 


90p'qqdqL 


‘eTTZ ejep e uty zeedde zeaeu ptnoys pue ‘sqoefqo 

wojsno jo seThuetz3 z0oz ATTeurejuT pesn st ¢ Tequmu odeys 
*z0qTpe eyy ut sexe qoefgqo eyq Bbutmezp zoz ATuo Aueaeter 
@Xe SPTSETS SzTs eyL “wey YATM peqetoosse seTHuetz3 pue 
sebpe ‘squtod saey sqoefqo woqsnd ‘“r0RTpe eyR ut qoeLqo 
eya Bbutqoetes uf pesn ,juTod joy, e439 Fo uoTATsod eyQ oF 
queaetez ATuo eze seyjeutTpz00D x pue x eyA pue ‘3yHTeYy syt 
8Q0S @ReUTPIOOD J SRI “STXE Z PTIOM SYR OF AZeTNOTpuedzed 
euetTd equtzuft ue st joefqo punoz6h y “uotqoeztp x euR 

uT SQTUN ,OZTS Z, PUB UOFIOeITp K SYR UF SAFUN ,,OZTS An 
Butoh pue 20Q0eA uoTatsod ey worzy Butqxreqs epts rey joue 
pue /ezts x ey Aq jes yQbueT e yaTM stxe x s,30eLqo ey 
Buote ButAT epts euo /z0Q00ea uoTatsod s,30efqo ey3 ye qutTod 
euo yt ‘suexzbotTetTTezed-euetd exe seoezains pue sTtToue ys 
‘zeqeurerzed ezts x eyq Aq jes sntpez xeTYyQ eaey sereyds 


punozy 

eutbeur Aq peqzoddns jou eoesins 

ATuo esn Teuzequt rox - Tebettt sqeceg 
seTbuetz3/squtod y3tM sqoefqo woysno STXW 
eutbeuy Aq peqzoddns jou TToueyAs 

ezeyds 


:eze szequmu 


90p'qqdl 





vices 


De 


480 ROM Kernel Reference Manual 


(L] sdozar 
(9] sdozar 
[sg] sdozar 
(y] sdozar 
{e¢] sdozar 
{z] sdozar 
[tT] sdozar 
[o] sdozar 


MOOINGD_ quar 
ONOHd_dudI 
MOINO_awar 
XONI_duaI 
XNIHS_duaz 
HONOw_dual 

CawH_daar 
WaIHLIG adr 


Jyo/uo yooTuep - BbeTz : 
yzo/uo butpeys buoyg - bey : 
FyO/uo mexrpyoTNS - Betz : 
wotqoezyzez FO xeput / 

(¢gz-0) xzoqoez ssoukutys / 
(§¢gz-0) xoqoez sseuqbnox ! 
(¢gz-0) zoqDex sseupzey - 
(s¢z-0) zoqjoez butpuetq -‘ 


*qzoddns 3y6yu eutphbeur veyq 3 
zeyjo suexbord 3ey43 setjzedozad yoefqo sutequod yunYyo sTUL 
‘[g] sdozar 


setqzedozd 30efqo ezouw ? aLAGA 


Atuo euthbewl - g ezts - Tddd 


*syqbuet stxe eyqq Aq peutuejep sezts YqQTM 

pue ‘uotqtsod j0efqo eq3 3e pezequUeD pTTos zeTnTbuejoez 

e Mezp 03 4nq ‘q0efqo ey z0z sohpe pue squtod ey} TTe 

MPIP OF OU TORTpe eYyR sTTER ‘Jes ZT ‘HeTzZ merpyoTns oT 
“Buyzeop xem ey yhnozy A 37 sexeu qoefqgo 

ey3 worzy 34HFT YOu Moy TorAQUOD sQUeTOTFJeEoD uoTsstusery 

eq, "wotyoeazex so xeput petzToeds eq q3TM WoOeLqo eYyQ UO 
Butyje0m xem e eyTT ButyAeuos ejeTNUTSs OF WUeeU ST OTNQeET 
Kssotb eyl, *,ueeqs, FO YUNowe ey ToTQUOD UOTQDeIzZer JO xXeput 
eu} pue sxoToo ,4Tusuera,, ey ‘/Assotb st yoefqo eyQ FI *j0U 
zo Kssotb eq 03 30efqo ey sqes Betz Assoytb ey “FFO QF surng 
eNnTeaA oxez-uou eB - yTneszep Aq uo st Bbutpeys Huoyqd ey, ~“seozrnos 
aubt1 Aq peqoeszze jou sft pue ‘(ysnzq gaI x0) 3oefqo ey worms 
Ki3}0exz{~p peex sft ZOTOD s,3F ‘*e°T - ATT ATIny se pezeptsucd 
sKeate st 300efqo eyqq ‘es st Hertz eqy Ft ‘sQ0efqo Teurrou 

z0g ‘jOuU XO sMOpeys qseD 03 AYHTT CUR sSQes QT ‘seDrnos AYySTT 
Zoqg *AOou ZO eDznos 3YyHTT e& st WOefqo eYA Teq_eYyM uo Hbutpuedep 
AyAuezeszTp pejezdzequy st SeTz Sutpeys eyy ‘“sseuySnor xew st 
GSz ‘qRooms st O - azeedde prnoys 30efqo eq3 ySnox moy sTorQUOD 
xzoj0ez sseuyhnoz ey, ‘“pezeyatp ATInZ st ggz - Wefqo eqQ UO 
pesn BbuyreyytTp JO AuNowe ey sTor_UOD TORORFZ HuytpuetTq euL 


[g] sdoza 
[py] sdoza 
[e] sdoza 
(z] sdoza 
[1] sdoza 
[0] sdoza 


woInd_aaa 
XSSOTD_dud 
ONOHd_dud 
3avHs_adad 
HLOOWS_dud 
aNaTa daa 


Herz FJO/Uo MeAIPAOTNS 
Setzy zzo/uo Assortb6 

Setz sJzo/uo Hutpeys buoyd 
6etz zyO/uo Hbuypeys 
zZoqoez sseuyqhnoxr 

($gz-0) zoqoez butpueTq 


*qzoddns 3y46yu zeatts oqany ueqQ 
zeyqo suexzbord yeyR setqzedozd joefqo suyequod yunyo stu 
[9] sdoza 


setqzedozd joefqo ezouw / anxda 


eutpSeuy Aq weRQTIM Jou - 9 EzTsS - Odd 


“sjods 

xZeTTeus seath TE FO enTea e pue sjods xze[Tnoeds peorzq seath 
oxez Jo entea y ‘“sjods zeTnoeds eq3 so ,sseuqyby3, eqy 
sTorqUOD ,QUeuodxe zeTnoeds, ey, ‘“zetTnoeds Attnz st Gsgz 
‘euoU ST QO -- UOT_AOeETJEeIT TeTNnoeds Jo qunowe eYyQA st PTSETF 
Aayzzetnoeds eyL ‘“uoTzeMosuT zeTnoeds suyequod yunyo sTyL 


/sseupzey 
‘Xqyxzepnoeds 


aLAGa 
anzAdo 


(Te€-0) 3ueuodxe zetnoeds / 
$Sz-0 3° ebuex ?: 


*eaoge ToOas ees - euTbeur Aq weyqtrm jou - zZ ezts - ogdS 


90p'qqdql 










‘oo’z Teaskzp (€ TO LOT - SseTD (Z ‘EET - TOWEM (T ‘OO"T - 
xztw (0 Agfoeds ¢-9 sedkq uopjzoezzex eyL “SGg°E O32 0O'T FO ebuez 
eqQ UT eq Asnu AT Os -- (QO0°T - YWoTQZOeTJer FO xepuT eNzA) » OOT 
ST PTSTF XOPUL SYL “PTeTF Xepul ey ut peroqjs xepuy eaTQoeryer 

»WOAsNs, eB sey joefqo eyy ‘p st edAq uoTQoerJer ey FI *s30eLgo 

AssoTb zo quezedsuezy z0x eQep uoTjOeTjeT sufequop YyuNYyoO styL 


ixepul 
fedkz 


ECAC: Fa 


uotqoerzzez FO xepuTt woyjsnod / 
/ aLAGQ 


(y-0) edkQ uopqoezzez 
‘yunyo Taga ees - eutbeuzr Aq we7ATIM You - Z OZTS - ULIN 


WaINLXaL_aaa - [y]sdozas 


peddeu oinqxe3 JT Tequmu erNnyAxeQ 
TIONSLS aaa - [e]sdozas 


‘ 
sqo0efqo [TToueqs Toy requmu TToOueqs / 

g pue x dem - ¢€ é 

g dem - Zz 2 

x dezm - T 7 

butddezm ou - 9 7 me 

edXkq BbButddezm ysnzq gar ‘ awam_dad - [z]sdozas 
(peddew gar 3T) zequmu ysnzq ‘ Hsnud dua - [Tt] sdozas 
ysniaq WiI - G : 
ypotueb - 7 
y~euzrou - oO a: 
odXkq eoezains ?/ 


gowmins aaa - [0] sdozas 

‘xeaTts oqang Aq pesn setqzedozd (eoezans) qoefqo sutequop yunYyo stud 
setazedorzd 30efqo / ‘![¢] sdozas aLAG 

eutTbeur Aq ueyqgTIM Qou - g ezts - Tans 


*KTuo syunyo Zsud Ut ere sueqt begxew pue eTeOSTIng eqL 









(qqbueT ueae ue exeu 03 Aresseoeu FT) ‘ped aLxAGa 


(peqeutuzre 3 TION 7ou) eueu eTTF Yysnzq / ‘(yqbueq]owen gLAzGA 
eueu eTTs ysnzq Fo yabuet / fqqbue7 anxan 
seysnzq peouenbes rox zequmu yseybty ¢‘ ({begxen aaomo) 
eNTeA eTeos TInz / (JeTeosTIng aaoma) 
‘sexe ysniq JO seqzeuypICcD TeDoT ¢ fuzogL WdaioaL 
sjeedez q3t™ dtTs - aITa_dvim 9T : 
ysniq butqeedex - Lwaama_dvum 8 ‘ 
uezptTtyo o3 Atdde - NRYGTIHO_avwuM fF : 
edky deim - Z_aqWwam : 
edXq dezm - x awam soit : 
:sBetz Sutddezm yqsnaq / {sHe tam aaomo 
epnataty - € : 
ZORITA - 2 : 
wofFpoeTzFed - T : 
ZOTOD - O 7 
:edAq yqsniq / ‘sbeta  aaomn 








(T°T wofezea) AtTuo eupbeur - ezts eTqeyTzea - zZsud 
(o°T uofszea) ATuo outheuy - ezts etTqetzea - TSud 









(qqbueT uese ue exeu oj Aresseoeu ZT) ped anxan 


‘ 
(peqeutuze3 TION 30u) eueu eTTZ erngxe 3 ¢ ‘{yq5ue7]owen @LxAGN 
eweu eTTF emngxey Fo yQbuet : ‘qqbueT aLAqa 
(pesnun ATquezzno) shetTz ze jeuezed / ‘{9t) sbetaa aLAGO 
szejeuered ernqxe 3 / ‘([9T] suezeg Lowdd 
‘sexe e1n3xeR FO seZeUTpI0CD TeDcT ¢ ‘uz0gL  WdaodL 

sCqo prtyo o3 Atdde - NOWCTIHO UWLXL - T : 
:sbeTy ezngxeQ / isbeta qaaomn 





‘pesn st butddew ernqxeq ueym eQep ernq4xeQ suTeqQUOD yUnYS sTUL 






Ajtuo eutbewr - ezts eTqeTzrea - TLXL 


90p'qqdl 


FORM and Chunk Registry 481 


IFF Specification 


*eaznqotd eyQ ut zeedde 

TIts eTbueqoez ey Fo szeuzOD py eYQ pue uot ZTsOod exeures ey Aq 
peutzep euoo zetnhueqoez eqtutsutT eyy ut sq0efqo Auy ‘stxe x 
8 ,BzeueD SYA UO pezejuUeD pue ‘03 reTNOTpuedzed eThbueqoexr 

tTextd ooz x oze e& eutbeuwt ‘yqbuet Teosoy ey pueqszepun 

o, ‘ATeatqoedsez sexe Z pue ‘x ’X eYA 4yNoge suoT WejOT 

xz0Z X pzemoz xX pue ‘xX preMCQ Z 'Z pxreMORZ ZX seQeQ0OZ eThue 
eatztsod yw ‘sexe ezeuwed o43 AnOoGe AXZ ZepxO eYyQ UT peurozied 
ere suOTAe_{OT EYL “sexe SQeUTPIOOD PTIOM ey A YyATM peubyTe ere 
Sexe sQt ‘orez [Te eze seTHue uotyejor eyA FI “stxXe Z eyQ 

JO uoT_OeITp eYyQ ut srnqoTd eyA Jo doq eyy yatTM ‘sTxe K uMO sqTt 
uMOp SHOOT ezreued ey, “sexe Z pue ‘xX ‘X EYQ puNoTe suoT_e{0T 
Kyyoeds pue ‘seezhbep ut eze seTHue uoypyAeqor ey, “yabueT Tev0z 
SAT pue ‘peute st At Moy ‘sT eTEUTeD eYQ STEYM STTSQ sSTUL 


yqbue{T [Teooz ezeueD Teed “owas 
setTbue uotqejox ezeurep feQeQ0% WOLOTA 
uotatsod ezeurep sezewed wOLOTA 

82 SZzTs —- ASHO 


* ()Bespeod y3ATm pepeoT eq ued 3eYQ ETNpoU spoo e 
yO oweu 9YyQ ST PTETF SUeUSeTTA eyL “YyunyO HSu@ se yeurroz oures 


cB OZTs - ULXL 
‘yung HSUd se WeuULTOZ oures 
cB SZzTs - ONLS 


*eseyq JO ouo ueYyQ ezou oq Aeu oxzeyL 


eweueTTy WHII aaI ‘ ‘ [og] eweueTty UWHO 


(L pue Oo weemjeq) zequmu ysnig /zequnN daom 


zB ezts - HSUE 
syxUNYo-qns OJNI 


“(s$z‘SSz‘SSz) szOTOD YyQTM 4Nnq ‘oeures eYyQ ee sqTNeyep ‘euThewl ur 


fatt AtayStazq you 

feomnos 3yHtT e jou ‘uo Butpeys Buoyd ‘/zz0o Assotbh ‘ggz ye Sutpuetq 
fozez 03 jes sseuybnoz pue sseupzey ‘zetnoeds /o00°T xeput yatm 0 edAQ 
uotjoerzexr /ozez 03 Aes szejeuered e1nqxe3 /seoezy 10 sebpe/sautod ou 
feureu ou ‘/oo¢g qe Agqtsuequt /oO°ZE TTe SspTety ezTs ‘sexe pTIoM 

eya 03 peubtTe sexe /(0’9’0) 3e uotatsod ‘/sedX3 eoezains TetToeds 

zo Azoyjs ou /edeys TeheTTt /ozez 03 Aes squUeETOTZyZEeOD uOoTssTusuUery 
pue wofqoeTzez /(0"z‘ORZ‘OPZ) OF 08 STOTOD :ere sqrTneszed 


*yeuotqdo jou st yunYO dWHS eUL 
“spTetg ,qunos, H5utyo yew yatmM TTe -- YAunyoO LsTL e pue yunYyoO LsTyY ue 


‘yUNYO LSID & eq OsTe yYsnu ezsyQ ‘yYuUNYS Towa & st ereyQ JT ‘TeAcemoH 
‘pettddns eze sqrneszep pue ‘Teuotqdo aze spTetTsy eseyy Jo Asow ‘uteby 


sejou Ssad 


90p'qqdl 


“squtod ,swzog, e432 O23 SATRIETEXT punoze peaou eq 30efqo Teer 
eyQ FO sexe OYA MOTTE eAcge szejeuered uoTJeEWTOFUeTA SUL 
suygtzobte Azeqetxzdozd e Bbutsn eseyR worzy peqerTnoTeos ueyy 

eze squtod [Teez s,30efqo ey, “aUMN » F + OUMN = Dd ST QUNOD 
qutod ey, ‘“peeqsut uweqqtTim st ernqQonz3s sty ynq ‘Ano uej4TIM 
you st eaoge yuUNYS ,SINd. 943 ‘sqoefqo ,suxog, s,euTbeuy r0¥g 


‘[Da]s3utod woOLOaA 
‘astusS UYOLOAA 
fuz0gL XIYLYN 

iped @aoM 
isbela qaom 
‘qumy qaom 
‘OumN qaom 


sjutod zoqTpe ,,suzo0g, 

uoFqetsuezy3 qoefqo 

uotTqeuzossuerq HutTeos/uotyzeqozr yoefqo 
peazreser 

Herz uotyqequetz0 

S®eDFTS FO TEequmU 

squtod uofqoes ssoz> Jo zequmu 


Ajuo euybeur - Od x ZT + 9G EZzTS - CHOU 


"orez eq AsnuU ZequMU TTEeD AsAzTZ eYQ pue 

‘qoeCqo peey ey3 z0oz eouenbes eyQ yaTm cezbe ysnu eyQ so Ared 
yore zo seouenbes zequmu [TTe> ey, “syxuNYyS CGINW JO seTies e 
eq TTTM ezeyQ ‘dnoz6 eyA Fo yoefqo yoee zoz ‘st VEYA - TTS 
ey3 UT yUNYS OSad HOWE uTYaTM ‘sqoeCgo ,eToAD, s,eupbeur tog 


“TTSeD AeYQ ut ezts/sexe/uoTytsod yoelqo urea waodL 
zequmu [Te /OUTTeEO SNOT 


Ajtuo eutbeuy - 99 ezts - CINY 
*eaoge peqtz=sep st erznqjonazys Axzoqjs euL 
*-qoefqo eyq zoz eanqonays Azoqs e ! !Xz03s XaOLS 
eutbeur Aq uweqqtzm jou - 9g ezTs - AULS 
‘seTztsuequt ad 39 ‘Y eqezedes sey ynq ‘eAoge SEINI OATT St STUL 
Aqtsuequt qyhHtT / tAQtsuequrl = YwOLOAA 
Ajuo eutTbeul - ZT ezts - TINI 


“3yBtT eyQ 09 souegstp eyQ uo puedep TTtm Aqtsuequt Azesseseu 
eyQ ‘seornos 3y6tT extT-duwet zoqg ‘eornos 3yH6tT eyQ 03 
UOoT_O@eITpP SYR Of AeTNOTpuedzed eze yoTYM seoesins Aoefgo 
say6tt ATInzZ 3yHTT eytTT-uns e oF gz Fo Aqrsuequt ue 
*sqoelqo eoznos ayStT z0z prety Agtsusequt ey st styL 


Aytsuequt yyhtt : ‘Aqtsuequrl=— Lowa 
eutTbeuy Aq ueqqtzmM jou - y EeZTS - SINI 


*ssouXutys umutxew sueeu ggz JO enTeA Ww “suoT Ae TNOTeD 
(uofqoeTzez) Autys eyy ut pesn ore seNnTeaA TEATTF eyQ ueyQ souts 
quezedsuer3-uou aq 03 yoelqo ey seorozs ozez 4nq ButysAue of 
At Butaqes ‘szeedde j0efqo eyQ3 Autys moy sTorquoD senTea 
Ze3TTZ s,qQoeCqo eyR YATA UoTQOeTEQUT UT ZoQDRZ AutTys ouL 
“sseuybnozr xew st ¢gz ‘YQoous st 9 - zeedde 

PtInoys yoelqo ayy ySnoxr moy sTozqu0OD zojDeF ssouyHnoxr sy 
gods yoy ay6T3z e& st ggz ‘ods qgzos Htq & st oO - eq pPTNoYs 
gods zetnoeds ey 3ybTQ3 MOY sTOTQUOD zORDeJ ssoupreYy eUL 
‘pezeyatp AT TnF st ggz - yelqo eyQ uo 

pesn Hbutzeyytp JO Aunowe syQ sTorquoD roQoOeyZ Hutpuetq euL 


90p'qddgl 





Devices 


482 ROM Kernel Reference Manual 


‘eaznqotd Teuty eyR UT (AOeTA - O AOTOD) AzOTOD yooTueb aeyQ 

03 3es XO ‘pazotoo eq Trt Axs yA zeyyQeymM storquoD Betz ,Axs 
yootueb, oy, ‘pesery eq oj sAex y wey eTOW Yon MOTTE PTNOD F 

gO yqdep eatosez e ‘AT TeoTZeTOEeYA Os - QuUNOD eYA FO UOTSTZA UMC 

sat sqe6 Xex yore ‘pooezq ore Aex eaTQoOeIzZeT & pue eATROSTFeET e& 

yaoq JI *,, Uadep eaToOseZ, SY YOROT 02 PEeMOTTE ASeASeU ST QUNOD sYQ 
pue ‘zequnoo yjdep eyQ squewezout Aez eaTQOeAJET/aAT_OSETJeT yorgq 
*yextd etbuts e zoz yoous TTTM zeoezq Aez oyQ sXex Jo requmu sy A 
sTor3u0OD ,YQdep eaTosez, eYL ‘“sueT woqsnd e rox yabueT Teooz eyQ 
Qes 02 pesn st puy ‘zeqsenbexz exzeued eyy ut rejewered ,ezTs wojsnd, 
2U2 SeUTA COT St zeqeuezed ,eztTs quezedde, ey, “uo sueeu orez-uou 

- Jy7O pue uo exzngjeez ,opez, OYA surng Getz Azzng/dzeys ey, *qoelqo 
ue 02 pexDery st erowed eyQ JT yQbueT TeDvos s,ezeuwed oyQ Butjjes ut 
pesn st 3r “woqsnd (pf pue ‘ojoydeTeL (¢€ ‘Tewron (z ‘eTSue opt (T 
‘Tenuey (9 03 puodsezz0D pue ‘zeqsenbex ,ezeued, ey UT sexoq ey OF 
Hutpuodsezzoo ‘y-09 wozy zequmu e st edXq suet ey_ ~“Hutpuetq TInz Tox 
Gsz pue ‘Butpuetq ou zoz ozez st zojDezy Gutpuetq Ays ey, “Sutoezrq 
Kez uy sotystzney eyA [TorQuoD sentTea eoueqinqred pue buthbpe ey, 


WALXa_ATD - [1] sdozq 
AATOSHa_aTS - [9] sdozq 
@ZIs_aTS - [s]sdoza 
gqvd_a1s - [y]sdoza 
SNIT aI - [Ee] sdoza 

aNa Ta ANS_aTS - [Zz] sdoza 
wanlugd_atp [1] sdoza 
ONIOGa aD {o] sdoza 


zyzo/uo Kys yootueb - bez 
(zeqsenbex steqots) yadep eatosez 
(moTeq ees) ,ezTs quezedde,, 
(steqoTb) snooz Azzng/dzeys - berz 
(moTeq ees) edkQ suet 

(ggz-0) zoqoez Bbutpuetq Ayxs 
(zeqsenbez steqoTb) eoueqznqred 
(zeqsenbez steqotT6) TeaeT ebpe 


BR en 


‘zeaTTs oqan, Aq 
“‘peztnbez exe syunys eseqy Jo 40g pesn ,setqredozd teqo tb, g so Aexzze ue !(g]sdozq aLAG 


- (set) Aqozezyey oqut pednozb Atqyssod sqoefqo zo zequmu Aue ue 8 8ZTS - OID 
ufequop Aew 3I “STS GdGL WHOd & Eq PTNoOYsS SETTF Teureqxe eu 
“eTTs yelqo Teuzeqxe we Jo euweu eyy suTeQUOD yUNYS sTYyL ZoToo 3yStT Auequqe fquetquy  woT0Oo 
ozez eq ysnu - o3hq ped ‘ped aLAG 
STTF Teureqxe eyQ Jo oueu eyQ / =‘ [0g] eueUeTTY ALAG 
b ezts - IGN 
08 8zTs - G¥OT 
TojToo YAtuez Y9TUeZ WOOD 
*TOQOSA STXE peAejor-un eYyQ YATM #709004 y pue ozez eq qsnu - 2e3Mq ped ‘ped aLAa 
‘2 'L 8, XTALWN 94 JO sqQonpord jop eyQ eze squeuodu0lD ZOTOD uozTzroy fuozTz0H wzOTOD 
Zz pue ‘x’x 8,sFxXe peqzeqQor e& 3eYR Yous sf woTReEQCT eUL ozez eq ysnu - 03hiq ped ‘ped aLAG 
‘,XFIQeW ATUN, & eq PTNoYs 4F pue 
‘sexe pTrom eyQ 09 Aoedsez YATM ST XTXIAeU WOT ReVQOT SUL 8 ezTs - OxMS 
“sexe TeROSOT 03 Qoedsez yATM exe szoqoez HuyTeos eyL 
*SO@QEUTPICOD PTIOM F SF TOQOSA UOT_IeTSueITQ SUL 03 Epes 03 TOTOOD qOU Jorepeg wot0d 
ozez eq ysnu - eqhq ped ‘ped 3LAG 
RTrTZeW woFRejor feqeqou «xa epez TeIORW FO SoUeASsTp ‘Aqgopeg = LOW 
sxzoqoez BHButTeos z pue x’x feTeosg wWOLOGA epeszy AITeQS OQ sOUeQSTP fqvepeg  Lowid 
ZOQOSA UOTRAeTSUeITQ feqjeTsuez, wOLOFA 
eT ezts - gdwi 
09 ©ZTs - XaLW 
“eaoge peutzep st erngonzqs Azojs euL 


syunyo-qns-qns ULxXa ezeues sy TOF eanjoONzAAS AYUOLS eB / !Kkz0qso. ss KUOLS 


9g ezTtTs - ULSoO 
“fo ‘8 ‘oot ‘o ‘o ‘o ‘0 ‘o€] 
oj jes Aexzze setqzedozd teqoTh pue ‘/(00T ‘OOT- ‘OOT-) 3e ezeureD “QT MOTTOZ TTT ereueo 
peyoezq-un ‘peqeqjoz-un /(08’08’08) O02 3e8 ZOTOD epezy /HOeTC OF eYQ ‘TSEATTS CqanZL eptsutT peaow st Aoefqo eyQ JT ‘esTMTEYIO 
qes szoToo 3y5TT QueTque pue yAtTuez pue uoztzoy ‘/ereureD eyQ 10Z YOeIA Q,UseOop ezouWeD eYQ ‘TION ST oweu ey JI °072 ,poeyoezR, 
Kzoys ou ‘/peutzep sernqxe3 zo ‘s{[TToOueAs ‘seysniq ou ‘ere sqTnesep SJ exeureo eyA 3eq49 Aoefgo ue Fo eureu eYyQ seTyToOeds yunYO sTuL 
eYL “Auesezd jou eze sxunyo ey3 JT petiddns oxze sentea yTneszeg 
‘yunYyo OANI ©43 st se ‘Teuotgdo eze syunyo-qns OANI ©43 JO TTIW ‘ [et] eweuyoes, aLAG 


8T ezTs - wWaLo 


20p'qqddL 90p'qqdl 





FORM and Chunk Registry 483 


IFF Specification 


‘IpHpeeyH { 
‘ped NOT 
/x 2bed 3srtz wo 3ON = 0 x/ febeaqqsata abr 
/x PA0ge seutyep word »/ fadxyobeg aLxEGn 

} qonzqs zepedéq 


HLOG_Sdovd euTsep# 
LHOIU_SIOVd SuTFopH 
LAIT_SIOvVd euTsopH# 
GNON SaDvd SuTsFepH 


/ 
queumoop zed zej00z pue zepeey eTbuts e smoTTe ATuo eqtzMorTd 
Ayquezaznd yang ‘szeq00z pue sxepeey eTdtyrnu sqzoddns jewroz sty :230N 
Ie ,O0F/Tepeey sty of BbuoTeq yuNYo TOIa FO ‘Rood ‘awaH ‘Dod 
e 03 dn pue yunyo sty Bbutmottos Hbutyqewz0z ydezbezed pue 3x03 TIW 
uotzoes rej003/zepeey utheq - LOOd/aWaH 


izpHood { 
‘zped SNOT 
‘Tped anazgn 
/» eaoge seuTyep word »/ f‘eTxasumnebea = LAGAN 
/» xequnu ebed Suzy qzeqg »/ /ebeqqzreqs a@aomn 
} 3onz3s zepedky 


e_AIALSAIOVA SUTFOEPH 
W_IIkLSAOWd SuTFopH 
T_UIALSIOVd SuTFEOpH 
I_UIALSIDVA SUTFOpH 
T IALSIOWd euTFEpH 


/* 
uotz0es Queumoop eyy o3 Hbuoteq yuNYo LoId FO ‘LOOd ‘AWaH * 
e 09 dn pue yunyo styq Butmo,ttos Buy jqeurozy yderbezed pue 3x09 TIv 

uoTqoes queumoop utbeg - 90a x 

*/ 

‘SIOTODOSI { 

‘[glszoToposI aLAGN 

} qenzys zepedx 


/* 


/x dD ‘QO x/ 
J Dd ‘A (WC x/ 
Je FTF UTE UF w/ 
/* III ‘II ‘I «/ 
Jn € ‘2 'T «/ 


syunYy INOd TOF Seop AT se uofAeTsuery ou seop 3T 
‘deu querino sqt eq 02 senTea eseyA syoeyo ATuo eqtxmorzg ATQuezinDd :e30N 
(e3ep AueumDop exzozeq) eTTz Fo doz Ae eq pTnoys 
sxequmu ZOTOD OSI OF SETTF UT pesn sxequmu TOTOD worzy se VeTsuerL 
eTqeq uwuopzeTsuezy TOTOD - ATOO / 
* 


far3quoa { 
/* wAUOzZ*,, FnoyZTM ‘peqeuTUIey TION »/ /* ‘[Jeuwen a@LxAdn »/ 
‘ezts  dyomn 


/x GS% °° O #/ ‘umn GALAGA 
} qonzqs zepedsq 


(e3ep AueumDop exzozeq) eTtTzF ey Fo doq eyQ ye zeedde prnoys sxunyo eseuL 
UOTAeUTqUOD OeZTS/AUOZ YOeS TOF sseyR JO suo ore ersYL 
eTqeq zequmu/eweu Quod - LNOd 


MOTTOF seznQonzAs yuUNYOD 


90P'dHOM 


z8xo WWHO_SWIL eutsepy 
Texo WHO Alva eutzep# 
08X0 UVvHO WONZOWd eutsepe 


/x 

a, Sze OOF pue sxrepeRey * 

ut Atuo pue ‘wwHO WANGOva ATuo sqzoddns ATquezxznS eytTImMerTg :e370N * 
suTA pue ‘eqep ‘xequmu efed zoz szoqoereyo AxeQ TeToOeds * 


*/ 


(.40/ oN. sTs/ sds) QIOXEN ANId_dI eutzep# 
(49, 1S,‘ 1,4.) AIOXEN DOsd_dI eutyep# 
Ca, 13,‘ Gs) AIOxXeN LXEL_GI eutyep# 
(a, M.'s) AIOXEN FOVd_GI eutzep# 
Cs, iW,‘ 1G) AIOXEN SEWL_GI eutzep# 
CN, We'd) AIOXEN Wavd_dI eutyopH 
Gs, 1D,‘ ,&,) AIOXEN SLOd_QI eutzop# 
Gb. 101‘ ,4,) AISXEN LOO_GI eutzop# 
(a, 1a,‘ sH,) AISxen (WaH_aI euTzopH 
(a. 10,‘ .0,) dIeXeN S0d_dI eutzepH 
(08.4774 10,4 1D,) AIOXEN UTIOO_aI eutzep# 
/* SHUNYD »/ (ibs oN 410.4 1d,) CIOXEN BNO AI eutzop# 


/x edky wrod x/ (.d./08,'.0,'.M,) aTexen GaoM dI eutzep# 


/* S8UTIEP WATI JO esn soxeW x/ wUWETI/ddI:, Spntout# 


~ 
*« 


“DUI ‘OTPMAFOS SUOCZTIOH MON 

JO QUesuoD ueAQTIM AnoYyATM peqqtured jou st eTTF styq ut 
PepntTouT seutzep zo sernqonzys eyy ButAs pom ‘suotyeottdde 
Tre pue Aue ut oTtF styR osn of poequezh Aqexzey st uotsstwieg 


‘pul ‘ezemqgzos suoztz0oH MEN LE6T (2) 3ybtzAdooD 
souTsep pue serzngonzys GUOM WIO™T JAI 


KeERK KKK K 


/ 


syxUNYD S3t PUE CUOM WYOM SeqTIOSep eTTF epnTouT sTyL 


* 


ruotadtz9seq WNuOd 
(sernqotd ‘squoz ‘zojToo sqzoddns) ebezojs quewumooq :esoding Wuod 


@aoM -dI Waod 


Waod 

“pul ‘ezemagzog suoztzoH men - ssoeTAeg souwec :Aq peqqruqns 

L8/€0 :pezqtuqns e3eq 
ANId ‘OOS 4 ‘LXSL ‘SOWd ‘SAWL ‘Wawd ‘SLOd‘LOOd ‘Away ‘Dod ‘wIoD‘INOd sxunyo 
qaom =Waod 

rsqI yunyo/wi04 

NOILdIYOsad MNQHD / WHOd JAI 

(@37tmMozq Aq pesn wuod Butssesoad prom) CaOM ‘FILIL 


(SUOZTIOH MON) JewWTOF Quoumoop e4TIMOCIa 


90P'GHOM 





Devices 


484 ROM Kernel Reference Manual 


/* PU® x/ 


fogurzota { 
sped aLAqa 
/* WeUIOS WATI OATT x/ /xoTopquezedsuerzz aLAGaA 
/« REUIOF WATI SNTI x/ fuozssezduop = uotssezduop 
/= YeuTOS WATI OATTI +/ ibutysen Butysen 
/x syutodtoep uy ebed uo uoTqeED0T y/ fsoax ‘soax qmaomn 
/» (Reu°"Q) uo st erzngqotd ebed yorum »/ febeg qaaomn 
/» sTextTd ul x/ ‘/aubteH ‘T3PTM qaaomn 
} Ronzqs zepedky 


/s 
butyseu yseWseHysu 
pue zoTooquezedsuezzysu sqzoddns Atuo ATjuezxNS eATAMOrG :e30N 
3e st eaznjotd ey ebed ey uo uoTAeDcoT pue ebed 
QeymM ynoge uot jewrosuT sepntout xunyo styq ‘ (weqsks qnoket-ebed 
® OATT) 3xXeQ Queumoop ey3 so ATquepuedeput pejeery ere sernzOT, 
yunyo Ado WAII Aq pemoTTos eq 3snHW 
uotq0es Ss~odq © ut eq ATuo ysnu yunYoO sTUL 
osUT erN_oOTd - ANId 


KKK KKK KK 


* 
~ 


febueyoosa { 
‘ped qaomoa 
*Z0TOD)«=«s-s HAGA 
feTxysostw 4 8=6aLAGN 
f‘etxys = aLAEO 
fumNju0g = aLAGN 
/» ebueqo Jo yunYo LXAL UT wotqecsoT rzeqQoeTeYD «/ fuoTAQREDOT aaoma 
} qonzqs zepedky 
/* 
sxeqoereyo say [Te TOF TOTOO/eETAAS/Auo_ oures SYA * 
eaey 20U PTP XOOTA LXAL snotaezd ey FF XUNYS sty epntout ATuQo x 
yunyo yore ut sentea zo Aexzze ue ssp * 
ASOTQ LXaL snotaezd ut sebueyo zoToo/eTAyas/quog - oosa 


* 
~N 


* 


"DRe ‘s,uanjey ou eT ‘YWHD WONASVd pue gez exe sxunyo 

LXaL tt eTpueyq ATQuezznD ues eATrzMord szejoerTeYo [230 ATuo eyL :e30N 
ydezbezed Azeae r0Z YOOTC LXAL e& 

eq LSOW ezeqQ -- yunyo Aqdue ue st styq ‘Aqduwe st ydezhexzed eyQ ZI 
ernjonzys eqezedes zoy peeu ou ‘AxeQ TeNQ0De st AOoTEA 

(qydezbezed zed yootTq euo) 3x03 yderbexzeg - LxaL 


Ke K KKK 


* 


90Pp"'duyOM 


eqep ou sey yuUNYS styQ -- zeyreW e qjsne 
yeezq ebeg - 3ovd * 
+/ 


idoasqen { 

‘ped gLxan 

eda, aixo 

/* syuyodzoep ul x/ fuoTatsod  ayiomn 
} qonz4s zepedky 
TWAIOGd_@WL eutTzop# 
LHOIY_AWL eutsop# 
UIINIO_AVL eussop# 
LIT GWL eurzop# 


/ 
WIINAO avL axoddns jou seop ATjuezano eATIAMCTd :e70N 
eBueyo yderbezed e xroz 
s6Huyt33es qej ey} TeASUSYM peqresUT eq PTNoYSs sTYQ ‘HUNYO Wad SYR SxTT 
xunYyS yore ut sontea zo Aexzze ue esp 
suotqen0T/sedky doqs qeq MON - Sav 


/qeuzogereg { 

‘ped SNOT 

/xw PAeTSUeTQ OF UIOD esn ‘Tequmu TeuzrequLT iXOTOD anAgo 

/x eaoge seutTyep wor f‘eTkasostw 8=aLAO 

/x sata eTkqs ebyuy pzepueqs feTaas aLAgan 

/xexed ut zeyo jsaty oz -oQe ‘eTAAS ‘umNQUOT JUmNQUoZ aLAGa 

/* n0ge seutzep word iAxyasuc 8 aLAGA 

/* Sacge seuTzep worgz /5butoeds aLAga 

‘upbzenaySta = =6agomn 

supbreMaszeT  amioma 

/* (T4p OZL) squtodzoep ur ‘quepul3zerT =qauomn 
} qonz3s zyepedka 
@NS_AIALSOSIW euTsep# 
UIdNS ATALSOSIN eutsep# 
ANON FIALSOSIN SUTFOPH 


/« 3dtzosqns »/ 
/* 3dqx0szedns »/ 


€ TInd AIILSAC eutyop# 
@ GHOTa_AdILsac eutsep# 
T UXLNIO_AdILsac eutszepH 
0 LAT AGILSAC Sutzeop# 


OTXO  STaNOd_Bovds eutzepH 
0 SIDNIS Bovds eutzep# 


/* 
sehueyo qeuros yderberzed oy zeacusym utebe pue ‘(00a 10 ‘aWaH * 
‘D0d) pe_Teqs st uoTADes MOU e USYM ASITZ peqrTesuT eq PTNoYys yunyoO sTyL * 
qeuroz ydexzbered men - wivd * 

«/ 


‘zpHaotd { 
‘ped auxaon 
*soueTaNn GLA 
} 30nzqs zepedka 


/* 

(€) eezy3 eq 03 seueTaN seztnbez ATquezaznod eATIMCTd :S30N = «x 
uofqoes eazngjotd utbeg - sod * 

«/ 


/»+ sdeuyjtq exngotd ut pesn seuetd zo zequmn x/ 


90P"dHOM 





FORM and Chunk Registry 485 


IFF Specification 


“dON © ST BZT- Epon e7hq eUL 
"eqQEp zo 

ge zkq T+u Aq pemoTIOF LZT 02 O Wors U Epod ALAG se per0ojs sej{kq peTzeEpA 
“seut 2 T + (u-) peqeedez eq 03 e3hq Aq pemotTos 

L@I- 03 T- wWory uw ENTeA epod aALxAG se pez0js eues eYQ se jkq Z ueYyR eTOW 


IBMOTTOJF se pessexduoo ATTenpTaTpuy sf SUTT UeoSs yore ueyQ ‘T=uoTssexduoD ZT 
*pessexduo> jou sft eQep eUTT ueDs eYQ UeYqA ‘Oo st eQkq UCTsseIdWOD CHW S42 FI 


“GHWE ©43 Ut peTzToeds st (seueta) 
yadep pue ‘aq5teq ‘qaptm ‘ebeuy ey z0z eRep Textd suyequod xdog euL 
uoftssexzdmop Apog 


"pS qe 


eUtTT weos euetd 


T T 
[I SUTT ueos oO ouetd 
Q eEUTT ueos u 


euetd 
SUTT uecs Zz euetd 
SeUTT weos T euetd 
© SUTT ueoss Oo euetd 
(IT = uopesezdwop aqHNa FT peqoeduoos ATTenptatpuy eutT youre) 
ISMOTTOF SE UOTYSeF peaeeTzequUT ue ut perojs ‘eQep Textd euyL 


ag’ 6g ae" 165. mas ow aepze. oga uF 
aow JO Ss{tTq eqQ se pejezdrejuy exe seuetTd xqoq ey peeqsut pue 
aYND OU eq PTNOYs ezeyQ ‘(seueTd ~Z XO ZT SXTT) WATI deep e ZI 
(e34q © ut peTsZTasnf 3zFeT queuoduoo yore) 

uu ol Oo szeqsTbex XOTOD AOF sentea ao 


“@poumMETA PTO eTqTyeduIOD e nok 3e6 prnoys eaoge peqtzosep 
B3Tq ey ‘TeAEMOH “OWWO SYA UT pezojs (pTepow) sxrequmu 
atq-ze xeTduos exouw eaeyq Aew swaltr o°z ebyuy meu 3eYQ SION 
“O8XO=ALIUGTIVH ‘O08XO=WWH ‘PXO=HOWI ‘0008X0=SHuIH ere sheTzZ 
sepoumeta ebtuy eucs ‘3yhtx eq Atqeqozd {T,noXk pue WYH 
eumsse ‘deep seuetd 9 st efeuyt pue ‘jueserd st yunyo SNWO 
ou JI “yUNYS sTyR eAeY PTNoys sWATI ALIUGATVH PUS WYH SOW 
yUNYo sepoumeta ebhtuy Teuotydo - SwYO 


(eacqe dump xey pejzerdzequt ees) 
poyjeu uofqoeduoa ‘yqdep ‘ezts ey ynoqe osutT - GHW 


(WHTII 943 O3FIMEer NOA FFT uoTQeuUXOZUT AqHtzAdoD Aue eazeserd pue 
syunyo qyftzAkdop (5) pue syunyo z0YRQNY HLNW 20F YOReM CETY - SE RON) 


ssyunyqo BuymMoTTos eyQ exe ebeut eyQ 3Q0e14xe 
023 YITA Teep oj peeu AtTeex nok ITTw ‘“WaOs AAI OTGuts ATaztez e& ST WATI 


sWwaII S5utqexzdze3ur 


2 abed syusWINSOg 44] |BEUOHIPPY 


OSXO=ALIUGITWH OO08X0=WWH PXO=FOWI O008X0=SAUIH -SEPpOUMeTA DWYO UOC SeION 


"29e -["mz"- Boo ee ee GAGSQWLL WS8AvOdd OALAILAO OOBAITIA *>0800 
“seeaar rrr tore AITAGGWS POSSWEPT OBA0008A OWEITOOO :0L00 
(eaoqe [T=uoTssexzduoD) peqoeduop -> eqep Apoq so y37e45 yqbuet 


6Sbbab7b FAWWAGOD OODOTIES WuWWYYYY :0900 
*-aog,abuq Buqb uqbu 


dass99aa 99774R99 TILLLLLL vySses866 :0S00 
qBbuq Bbuq6b uqbu qbuq 


Q°dado00d"* *""* EEOOSSSS SSEEEEEE GS000072 O000RaTT :0700 
n65ez nzy3 ofex zoz exe s,qba > 5uqb uqbu qbBuq 56uqsb 


sotto ccawmontt: BAOOTTOO O€000000 OSTravE vOB00000 :0£00 
FOVI=p | WYH=008 epoumetA -> uq5y yybuet ,d Ww WO, epoumeta 


“ ctomWoT aT 70000000 LPCYIbEr O6TOOPTO HOWO0000 :0z00 
yUnYo sepou META BOTNY-D FO QzeGs -> yIbueT LOW WO, Yeambea adsyuerL 


FNS TE et Oe 00T00090 00000000 O6TOOPTO #TO000000 -OT0O 
peg uotssexduop yseN seouetTa —> pacowWta Broxbzox yStHeptm yabuet 


CHWENE'TII’ Pp” “WaOr PPSPAbCh AYZPOvEY BTY9TOOO AbzZsar9b -0000 
yunyo xzepeeydenatg Jo 3ze4s->,d HN GWA TI, yabuet WUO A, 


ruoFqeqerdzsaqur 


“ttyanttr tp AATIGUZ HYSSWBYT 0898400082 OWE9TO0O :0L00 
Raog? 2 eer 6SbR4b7 AAIWWAGOO OODOTASE WuWWYYYY :0900 
seyty ty 'dddga’ aags99aa 99773999 TILLLLLL b¥SS8866 :0S00 
O*adaoooa"* *** E€OOSSSS SSEEEEEE GSG00007Z CODORTaa :0P00 
sot tgc capo” AXOOTTOO 0€000000 OSTPaPEF 70800000 :0£00 
oWwo" "a" 70000000 LYCYIvER O6TOOPTO OKO0000 :0z00 
00T00090 00000000 O6TOOPTO ¥TO0D000 :0TO0O 

CHWEWE'TI"P* “Waod prerarcey Aryzyporer BTY9TOOO ArzsaP9y *0000 


‘aryunyS ze930eT-y yxeu eyQ 03 (yqbueT ppo ZT T+) yQbueT 

ateyq BbButxyees Aq syunyo umouyun xo pepesuun qsed Bbutddtys ‘setts gal aSsuvd 
nox ‘“yunyS ey Fo ysex eyQ Fo yRbuetT 3tq-zE e Aq pomotTos ‘qrIyunyo 2933°eT-p 
e YAM sQzeqs sqzejys yunYO yoey “WYO & UTYATM syuNYS Jo ‘wroz yseTduts 
ITeYA ut ‘pesoduod exe seTTF ddI jeETTF SYR OQUT Aeszzo TeTNoOTAIed Aue We 
Huteq yunYS WHTI ze[TnoTyqzed Aue uo puedep zene TON ued nox je jou queqroduy 


<WaTI ue yo BbButuutbeq so dump xey eTdures 
‘qeuroy gaI eTqeszed pzepueqs © sMOTTOS QI * (deNATa peAreTIERUI) WATI WHOd 


pettes st ebftuy eyq uo sebeut otydez6 zoz (qewrog eTtg ebueyorequr) aa euL 


sopoumeta ebyuy pue seTta WHII ebtuw ggI 02 OFQUI 


| e6ed syuswinood 44] /euOnIppy 





vices 


: De 


486 ROM Kernel Reference Manual 


-ebeyoed zeyATe OqUT pepeoT pue (peTTeysut pred 
pzeoqebptiza WaD & eaey nod 37 ebtuy znoX septs WHI pue ebyuy eqq w0e9SeMmjeq 
Zo) seuTYyoeU eyQ ueemjeq perzzessuezy oq Kew setts ofydexzh WaII euL * (WAI 
ue uo uoTsueqxe eueUeTTZ ,WqT’, B esn og eaey Aeu nok ySnoyy) etqtyeduoo 
eze sebexyoed ,rr3utedd, ebtuy pue Wal sqaw OTUCTQDeTT YQTM peVzeerD sWHEII 


“yapta 034q wens ue 03 pepped eze (seysniq se 
yons) sebeut zeTTeug ‘epta seqXq zo zequmu uese e eq ysnu seheuy swaTr ebtuy 


:S890N 29490 


“sZOTOD eqnTosqe 

y9 03 dn eptaozd ueo styz ‘“sseuqybtzq sTey Ae peXetdstp st Textd yeyq ueqq 
“({T) qes st euetTd qseT oyQ ut 3aTq ey FI * (MUNYD AND EUR UT peTsTOeds st 
zeqjetbez roToD yore roxy senTea gqou) srequmu zeqstTbez ToTOO Teurou se peReer3 
eze souetd zeyj0 eyy UT SATq EUL “YOTReEOTF}pow ALIUGATWH se eueTd yseT 

e©”U3 UT AaTq eyQ sgerdrequT ebyuy eyy ‘epouw ALIYGATWH UI “TeTdUTs st eNO sTUL 


IS¥IOM pou ALIuaaTwH ehtuw mon 


p obedg 


syuswinoog 44] [euOnIppy 


€-0 seuetd worz s3tq yATM Queuoduos useerty Hbutoetdez ‘snotaezd ptoy 
€-0 seuetd worzy sqtq yATM QueuoduIOD pey butoetdez ‘snotaeid poy 
€-0 seuetd woxry sqtq yATM Queuoduos entg Bbutoetdez ‘snotaerd poy 
xeput zeqstbez zroTOD Tewrou se ¢-O seueTd espn ‘UOT IeOTF}Tpou ou 


2SMOTTOF 

se peqerdzequt eze (g pue y souetd) seuetd omg QseT eyQ UT SaTq WoTZeEDTFTpow 
ZOTOD ey, *(0 re4sTher) TOTOD rTeproq eyA FO eNTeA gOU eYy seTstpou yt ‘Textd 
UOFReOTFTpou e st SuTT ueos e Fo Textd AsztzF eyA JI “Textd quezrnod eyQ z0;z 
atnsez eyq Aetdstp pue (Aztpow) queuoduios g ro 5 yY s,ZOTOD snoqtaerd eyQ FoF 
€-0 souetd ut sqtq y ey3 egnaTasqns ‘(pue pToH) Textd snotaezd ey Fo enTea 
qu SYR SYR OF ‘epow WYH UT ‘eHtuy ey esned YOTYM sATq UOTIeOTFTpow TOTOO 
aze seueTd oma 3SeT S43 UT SATQ CYL “AuUnYO aYWO WATI Suz ut peTsyToeds eq 
PTNOM YOTYM sTOTOD eAnTosqe 9T 03 dn Hutath stextd zoToo eqntosqe butAztoeds 
zoz seuetd p sey erznqotd nH euetd-9 e og ~-Textd quezinod eyA Jo FOTOS 

ey e3eeID 03 SUTT eYQ UO TexTd snotaerd eYyA Jo TOTOO eyQ of UOTReOTFTpou 

@ Zo 5 y Ue SqTIOSep seueTd 4seT OMQ SYR UT SATq ey ‘Spou WYH UI 

‘senTea gou 960P TTe Aetdstp ebywy ey sqeT epow (Aytpow pue PTOH) WYH ebtuy 


isyz0m epou WWH ebtuy MoH 


‘ebtuy ey} uo YIOM ALIUGITVH PUE WVH MOY pueqszepun 
qsnu nok ‘eutyoeu zeyjoue oq eznjo;d FLIYaaIVH 20 KWH e& 3r0odsuezq o7 


“g08 37q 08x OYA eAeY TTTM soTd aLIUaTWH 
“SOPOMMOETA ONYO UT 22S 3TQ 0OOSXO SYR SEALY TTTM SNWO 3TG-9T © YaTM soTd WWH 


“sbeTz epoumety, ebtuy 3tq-ze e243 weyQ pue ‘yqhueT yunYyo 3TqQ-ZE 
eyy Aq pemoTTos st ,DWWD. 843 ‘xUNYD OWWO e ees nok ZI = =‘“WHH ATqeqozd st 3T 
‘yunyo ONYD ou sey pue deep seuetd 9 st ezngotd ey3 Jr * (aI yuUNYD reqoereEYo 

-IIOSW-P © YQTM QzeQs TTe AeyQ - syuNYyo eYyQ SES TTT nok -— uofqeqerdzequt 
IISOW U3tM ETTZ znoXk Fo dump xey e Ae YOoT) yunyo owwo e& peaes Atredozd 
2t peaes jey3 ebeyoed eyQ ‘SLIUGAZTWH 20 WWH ST eznqoTd eyy ZT ‘AT Inzedoy 


“K~quezessTp peqerdzequt st 3T ‘SLIMAAIVH IO WYH St eangoTd eYyQ JT - End 


* (uofantTosez zoToo unb-xzed-jtq-g YATM pezoqs sem ZOTOD 

eu? JT SIEP PTTEA uTeQUOD ostTe Aeu eTqqtu MoT eyZ “eqhq e Jo eTqqtu ySty 
ey UT pezrojs yoes ere squeuoducs g pue ‘5 ‘y ebtuw atq-p “eT) "s3tTq-g oF 
peTess queuoduicos yore yqTm ‘gq Fo 03Xq euo pue ‘5 e3kq euo ‘y Jo a3kq eo 
se pezojs enTeaA goy s,zeqsTbez yore yQTM ‘0 reqstThHexr yqtm Supqzeqs ‘WaTI 
eu JO YuNnYO AYN S44 UT pezojs st TeqAstTbexr ToTOD yore TOF eNTeA qo SUL 


6 = TOOTO Azeutq zeqjstbexr roTOoO sesn Textd WeyQ useyQ 
TO TO TaxId 
oT ee aNwid 
7€ pue oO 
seuetd ut jes st Textd zernoTqzed e roxy ATq eYR pue ‘seuetTd g eaey NOX ZT 
‘*e'y ‘souetd ey3 nzy3 Textd yore qe Butyoot Aq petztoeds st Textd yore 


xoz pesn zeqsthbez roToD «‘eqep Textd zo seuetd N eaey TTTM nok ‘Azessopeu 
37 Suzqoeduooun pue butszed zeqze uey ‘3LIUGATWH TO WWH 3OU ST WHTI UF FI 


reqeq eutd ueog oyQ Bbutjerdzequy 


€ bed s}uswiNdDOg 441 [EUOHIPPY 





FORM and Chunk Registry 487 


IFF Specification 


IFF Source Code 


This section contains a variety of source code listings showing how to use IFF files in applications. 
All of these programs require the new iffparse.library included with Release 2.0 of the Amiga 
operating system (Kickstart V36 and greater). There are four parts: 

e IFF include files. These have been updated to be compatible with iffparse library. 

e Link modules which provide convenient IFF handling routines such as showilbm.c. 

e Example programs showing how to use the link modules. 


e Stand-alone utility and example programs. 


IFF Specification: Source Code 489 


uooT Ue YATM ‘WATI ue se users Quozy sy Q eaeg sARBSUseIDS 


suofqounz yoedun/peot Apoq pue ‘otpnyescoto 
‘otpnyuedo ‘etduresietg ‘etdurespeotun ‘etdurespeot - 

queumzysut Zo Aoezze punos xasg ue sketd pue speoy xassheta 
(qzed moys ey seop yjsnf ‘euweueTTy ueath JT) sutq e& 
qe seuetd » 37 smoys ueyA pue NATI 379-7z eTdutTs e seaes 
WATII we 02 (MEYORWHTI wors) eTTFZ roToOo/eueTd mez syzreAUOCD WETIOWeY 
STTF ToToo/euetd mez 03 WATI we sqzeau0D MEYOWNATI 
epoDd eoxznos Oo se WHTI we sqndqno DoqWETI 

ueezos HBbhutqstxe ue OUT 3T speOT pue WATI ue setrend 

qutzd -3do ‘WaITr ue seaes ‘ysniaq © speotT ‘WHTI ue sXetdstq 


owedatqye 


(seTTFOXEW ees — soeTNpou qRTM ebexutTT ertnbez eseyy) SNOIIVOI1adv 


*uoTAouns yore uo sDd0p TOF Spod eDANOSs sTNpou ees 
@TNpowu qoee YAM PeAsTT ee suoT_OUNZ Tnyzesn ouwos - ALON 


SNOILWOIIddy GNW SHINGOW d4iI 40 LSIT 


“eTQeATOTOD<-uqT FT 03 seDuezezez euros Aq 

OsTe pue ‘prety * ALAGN & 03 peubtsse queqsuoo Sutzqs yore 

ZoJ peqezeueh eq 03 suees Hutuzem e ‘xueW 4QTM Buy TTduop ueqM 

*qrsoqozd qtte Aq ut petind st ettz epntouy dzzq3ew ey3 

anq ‘dgyzy jeu esn jou op setnpow osey, ‘“y" dssyqeu/sepzerqttT 

ut ()sqe FO uOTATUTJZep TeucTyTpuoD eyR Ano AueuMIOD OF pey osTe 

I ‘xuey zog *(OTp3s xXUBW pue SYS YIOq YRTM AOTTFUOO YOTYM 

osTe sojozd ofpys qtT ebtue eyQ peutequod eTTF epnTout styy 

JO suoTSIEA TepTo) ysojozd qTTe T° LE FSeeET Ae eveY Qenu nox 

‘attr ebtue 0°z pue setts epntout (T°LE) O°% 43TH ‘PO'S O xUEW pUe 

20T°S D S¥YS B5utsen pettduo> ueeq esaey soTdurexe pue seTnpou eseyL 
SALON NOILWIIdNOD 


“qeuxoz xeTduoo e eptsut punozy sem eTTZ aznoA ueyQ 

‘(oxez-uou) GNUL FI “PTOFF ung“ osureszeg’osul (wos) eyA yoyo 
‘PROT & TEeARFe pezeque sem wIOZ xeTduoD e JT euTWIEQEp oO] 
*sernqotd zeqqo pue oTsnu sty esoT 02 zesn eyQ Bbutsnes 

‘WHII eTduts e© se qno yoreq AF eAes UEYR pue ‘OTsnu pue semnqoTd 
Huyuzequos SIT xeTduod e Fo 4NO WAII ue peer ptnoo wexrboid 
quted e - etduexqg -‘wexzbord znoXk y3tM 37 zeA0 Bbutytim Aq 

Sts xeTduos sty Aoxzqsep ATHuymouxyun Aew zesn rznok ‘estarey oO 
“qeuzoz xeTduo> eq3 ButqeerDex Jo eTqedes exe NOx sseTuN sznDD0 
stqq weym zesn znoX uzem prnoys nok ‘uwexzbord eqtim-Az}pou-peez e 
exe nok zt ‘zeaemoq “3eexH st STUL ‘Ut peysezeqjuT ere noX AeYq3 
WHOA OYA PUFF 02 SWOT peqseu pue ‘sSLSIT ‘SSLWVO Se Yous syeuToz 
xeTduoD 1934Ue TTT eTNpouw o-eszed oy, - sMIoOd xeTdwop butprebey 
SWUOd XaTIdNOO ONIGdWord 


* (QsTTXUNYDeezzy ‘AsTTXUNqoeATIAmM ‘YUNYGOputsZ) eTnpow sxunqoAdoo 
eqy UT seuTqnor eyQ eTA sxuNYyo petdos rznok eAedoTTeep pue 
(qstm nod Zt) 34No Yorq OATIM TEReT pue sseode vey, * (D°oszed) 
()eTTZtesoTS AtTzee ue op pue ‘sxunyo pezeyyed xznok zo Kdoo e 
eqeexD 03 (D>*syunyqoAdos ut) syunyoAdoo esn ued nok ‘uedo 
3fun zo eTTs eyQ Bbuydeexy Fo peeqsut ‘os “Ano yoeq ETTF 
eY3 EATIM Q,UeD NOX ‘uedo st ETT & STTYM puy “ATUN eYyQ OF 
dt1T> ueo suofqjeottdde zeyjo ou ‘uedo st qtun pzeoqdt{o e 
STTYM ‘uedo pzeoqd}tTo ey3 YO eTpuUeYqeTTZ e deeyx 07 eepT 
poob e& jou st at ‘zeaem0H ‘sxUNYS pezeyqqeb ey Bbutsseooe 205 
(() wozqoeTTooputa ‘()doxaputa) suoyqouny esredzzt AOeITTP UO 
(eqepdozdputyz se yons) suotqounz o‘eszed esn Aew noX ‘uedo 
ST eTpuey eq3 ETTYM “uedo (pzeoqdtID ZO ETTZ) STPUEHAAI 

ey deey suotjounsy peoT TeaeT-zreyhTy ey FO ISOM - SALON INVIUOdNI 


AWQGVSuY'SPINPOW dal 


*s ,ogur[wz0z] eeDo0TTeep pue ‘()aareeta ‘dn ueeto 

‘u 4tun pzeoqdtTS e4TIM/peez oj pesn oq Aeu [u]o- 

eUeUeTTS euL °()eTTF}FesoTO pue ‘ () qaxeqQuoozjxeu/ () 3xeqQUODIES 

/Qettzteszed ATuo-zepeer ‘()eTFZTuedo o-eszed TeaSeT TEMOT 
ey esN To ‘suoTQoUNZ eaes/peoT TeasT ySty peptaozad syA espn 

* () dAIDOTTW 

eszedjzt ETA peReDOTTe STpueyadI ue o9 pue ‘shexrze yunyo 
Pertsep eyQ OF serNjQoNAzAYs eseyR Jo 4xed OFuULesTeg eyQ SZTTETITUL 

* (qi ddeuqtt/dszt 

UT peUTFOEp OFUIWATI ue eTdurexe z0oz) y"dde[wroz] /dzzt 
uy peuTysep se serzngonzys osur[wxr0z] eroOW IO suo SeRBDOCTTIW 
(A[Tuo szepeez) syunyo peztsep ano zo sXkerzxe exyt{T-beq sutyeg 


teze eTnpou o*eszed eyq Bbutsn Jo 
qdesuos otseq ey ‘“‘eTnpou o*eszed eyq uodn 3Ttnq ere suotqeotrdde TIw 


“eDTMQ peezy eq AOU TTTM suoTReDOTTe 3eYR Os szrequUTOd 

eqetadoazdde ey3 4no [Thu seutTqnozr dnueeTo eyL “ysnxrqpeoTun eTA 

dn peueeto eq ueo qutod Aue je sTtezy zo speesons QeyQ ()YUsnzqpeotT e 

‘eTduexe z0qg ‘“seaTesueyy rox dnueeTo eses eptacad oj peubtsep useq 

eaey seTRpou eseyy ut peptaoad sated uotjounz TeaeT-yhty eyQ Fo 3SOW 


‘epod ()weerz3s ofp3ys styq O73 Hbutzesznq TeuotyTppe umo anok ppe oF 

quem Aew nod ‘uotqeottdde aznoX uo butpuedeq ‘o*eszed ut ()weerz4s oTpys 
yOeqTTes ey ySnozyR seutqnoz or pezesznq umo s,zeTTduoo anoX esn ued 
eszedgzzt eouts epoo dnpeeds or of6 eyQ 3z0d 03 Azesseoeu jou sem AI 


+Kxzerqy{‘esxzedgztT FO VUOTANCTIASTP MOTTE OF ESUEDTT YOuSeqyTOM ET TFEUR 
03 umpueppe ue 306 Kew zo ‘esuestT qyoueqyzom 0°Z e& eqnoexe Aeu sqonpozd 
Teporeumo> zyeyR uo Azerqy{’esredszT SAngTIASTp OF YsTM OYyM szedoTeseg 
‘E€°[ xepun y20M ostTe anq ‘0°z Jo ebequeape exe3 07 peubtsep ueeq eaey 
seTduexe pue seTnpouw eseyy FO TTe yey pue ‘ArexrqTT etTqtqeduop-¢E°T e 

st AzeaqtTeszedzzt QeYR EQOU EeSseETA “0°Z YOuSqYTOM UO peqnqyzystp st 
yotym Azexrqttesiedzzt ezpnbexz ezey pequeseid suotqeottdde eyy JO TTIW 


‘u qtun preogdtTo se ("290 4yZ2-n ‘nTO-n ‘nD-y “OF) [U]O- oureueTTT 

ey sqezrdzequy ()eTTytTuedo s,o°esized esneoeq seTnpouw qdiI SY} osn 

qeyq suopzeottdde TTe z0oz oFQeEUOQNe st Aroddns pzeoqdyTO ‘uoTITppe UI 
“squoumzjsut pue setdues sXetd AtTTenjoe mou eTdurexe xASg EY PUY 
*(syunyoXdoo) syunyo Bbutppe/butazesezd zoz pue (dumpueexos) butquyad 

IOJ peppe ueeq eaeYy seTNpPoU MON “TTOTOso3ne pue ‘TorRU0D Aouerzedsuez3 
zepzoq ‘sdtto Aertdstp cepta-T[nzy ‘sueezos ueDsTeEAO pezeqUeDd se YOns 0°Z 
zepun suot3do meu Fo As0y & eptaord ek eTqtzeduoo-_E*T ere YoTYM suoTZoUNT 
6Buyuedo-Aetdstp tnzxemod sepyaozd e[npow o-ueezos ey, ~“suotqeottdde war 
eyo Tereaes pue weshord Aetdstq 0°Z ey TOF SeTOpoumioD ye esnoYyUT pesn 
ueceq eAeY esoyy 03 ABTTUTsS seTnpow ‘AueudoTeaep zteyq3 Hutanq ~ sna TI 
Butaes pue ‘BbutXketdstp ‘Suypeot ‘SuyAzenb xzoz suotjouny esn-o03-Aseo 
TeseT-ySty meu Auew utequod seTnpow meu eseyR ‘epts sntd ey3 uO 


‘pebueyo eaey seoezzequyT uotTjouny TeaeT rzeyhSty ysour pue sernjoni3s 
qsou ‘zeaomoy ‘epoo Teushtx0 eyA FO Yonu utTejez o7 eTqTssod ueeq 
sey 37 ‘seTHpow euos ul ‘epod aaI wa Teutbtz0 eyy rox squeweoe[dez 
se peubtsep exe setdwexe pue setnpow epoo AzerqyT’eszedszt eseyL 


S°LE UOCTsreA 
Teet Atnc - setnpow dial 


AWGVSY'S9INPOW dal 





vices 


De 


490 ROM Kernel Reference Manual 


> 
(sOWIaT)$ (Zadw)$ OL 
(SAITAN) $ GFT ebTwe:gIT ATT 'OT:ATT AUWUAIT 
(OZdd¥)$ O° D:4TT NOdd 
> HLIM> AUTTIG 
(ozaaw)$ = (Zdaw)$ 


> 
(sOWLaT)$ (Tddw)$ OL 
(SAITAW) $ GFT ebywe:aqIT ATT OT:AtT AUWUEIT 
(oTdd¥)$ O°O:qQTT Woud 

> HLIM> AUTTA 
(otddy)$ = (Taaw)$ 


uofpqeottdde qoee z0oz obexutT # 


(gdaw)$ (Laaw)$ (9aav)$ (Saaw)$ (vaaw)$ (eaay)$ (Zaav)$ (Taaw)$ :TTe 
suofTqeottdde eyqQ FO TTe SexeN # 

F° wse- yo 3° O° > SaxIagaons* 

> SaxIagaos * 


osddyv 
OLdd¥ 
o9ddy 
osddv 
ovddy 
oeddy 


(OMMMII)$ (OSWHII)$ (OTNEII)$ (OUNETI)S (O4SI)$ O° (GdaY)S 
(OMN@'TII)$ (O44I)$ O° (Lad¥)$ 

(OMNEII)$ (0441) $ O° (Qda¥)$ 

(OMNEII)$ (OUNATI)$ (O4dI)$ O° (SdaW)S 

o-oqutazduq(W)$ (OTWHII)$ (OWNHTI)$ (O44I)$ O° (VdaY)S 
(OdaI) $ 0° (Cdadw) $ 

(OSHATI)$ (OTWHII)$ (OUNATI)$ (O4AI)$ O° (ZdaW)S ozday 

o* sxunqoAdoo (Ww) $ o*dumpueezos (W)$ (OWMTI)$ O° (Tdd¥)$ otday 
etduexe uotqeottTdde yore Aq pepeeu setnpow 3oefqo euL # 


sddv 
Ldd¥ 
9ddqv 
sddv 
vddv 


owedatqpz/owedatan (w) $ 
WATIOWEA/NATIOAMEY (W) $ 
eaeguee2zos /eaegueejns (¥) $ 
MEYOWRTI/MEUOINATI (VW) $ 
DOANETI/DOINETI (W) $ 
xaseketa/xassheta (wv) $ eaay 
PEOTHETI/PEOTNETI (¥) $ zaav 
OWSCNETI/OWSGWETI(v)$ = Tddv 
suotqeottdde eszedzzt xno # 


OWaLXa 

owd'TI 
OMWa'II 
OINaTII 
OsWa TI 


o°oqutadurq (W) $ O° dumpueerzos (Ww) $ O° syunqoAdoo (WH) $ 
(OMNGTI)$ (OSWHII)$ (OTNATI)S (OMNHTI)S (0441) $ 
o-zeyoed (K)$ O- MUTT (W)$ O-uqTTOAeS (WH) $ 

o* deurtq3eb (W) $ O-WqTTPeOT (HW) $ 

o*ueexzos (W)$ O° AetTdstpjeb (w) $ 

o*zexpedun (WN) $ O° TUITT (WN) $ OuNa'IL 

o* OOH (WN) $ oO’ eszed (W)$ OdaI 

UTA YAUET OF setnpou yoefqo jzoddns eszedzzt zno # 


/sdde v 

/seTRpou Ww 

CN HOLWa OS = SOWIZT 

?3QQTONIT- = SOWTaY 

I@QQTONIT- €Lf- a- bastzo- = sowlad 


use = 
2T = 00 


att Snqep:aIl =saI ANH 


SVS'SIHO1FN 


*suotgse6hns pue sjueumioo zfTeYyA TOF rSeURIATAE wyor pue uojIeEG TT} oF pue 
“Katttapqzeduos sws/xuen zoz sebueyo epood sty TOF uoATeM eves OF SYUeYL 


-Kzoj0ezTp epntout utew znoX ut 20 
Kxzojoeztp Auezzns zno0ok ut ydey eq Aew Azoqoexztpqns styL a’ e#/dgszt 


SUIId FANIONI 


D*oqutazduq 
2‘ dumpueez0s 


@pod Dd se WHTII 3ndqno 03 eTnpoW 

(pezatnbez jou eszedszt) etTnpow butqutad ueezos 
astTyunyqoeezy ‘QeTTyXUNYDeATIAM ‘yunyqoputs ‘syunqoAdoo - 

seutqnoz Sutytzm 3astT yunyo pue Sutuorto yunyo o>‘ sxyunyqoXdoo 


SAHINGOW WaLxXa 


zexyoed xq0 d'zeyoed 
Kaodand ‘dWWOANd ‘CHWAQTUI - 
(p'zexoed sTTeo) seutqnoz eaes roOTOD/Apoq WAII TeAeT rEMOT D"MUqTT 
wqTTeaes pue eAesueeIDS - 
: (a"MUqTT STTeS) 
seureueTty pessed exe yoTym seutqnoz Bbutaes WaTI TeaeT ySTtH 


SUIQGOW JLIUM WeTI 


zeyoedun xq0@ >*zexyoedun 
(pTepou seqeez> x0 seb) bureojeb ‘eTqeqrojTooDeTTe 
‘szoToDeezy/sxoToojeb ‘deuopeot ‘Apoqpeot - 
(o"zeyoedun sTTes) seutgqnozr peo, z0T°0D/Apoq WATI [TSseT TEeMOT D*auUqTt 
atdtrio ‘yoeqtTeszepow ‘ueezosptuedo ‘Aetdstpuedo - 
S[Npou MopuTM/ueexzDs eTqTyeduios soq-uou/sog 0°Z/E"T 
Ketdstpeqjetep/Aetdstpeqeerz> ‘uqTyMOoysUNn/uqTTMoYs — 
(e*muqTT ‘o'ueezos stTTeo) Aetdstp/peot deuwqtq 
deuytqeerzz/deujtqqeS ‘ysnzqejeTep/yseniqe jeez - 
(o°azuqtt strteo ‘Aetdstp-uou) Hbuzpeoyt deuwyrq/ysnzq 
uwq ttAzenb pue ‘uqTTpeotun/uqTTpeocT ‘YsnxrqpeoTun/ysnzrqpeocTt - 
(deu3tqq3e5 stTTeD) 
seweueTTy pessed ere yoOTYM souTQNor peoT WATI TeaeT yStH 


D> users 
o°Ketdstp eb 


2° deuytqqeb 


D"UQTTPeOT 


S@INGOW dvad WATI 


euT{ANoT TozZe 4xeQ TTeqZgGI pue ‘uotTjounz HutyqtiMm 
yunyo yOynd ‘sTAunYoQuezInS ‘sTAxXeQUOD ‘AxeqQUODQxXEeU 
‘gxeqQu0030e6 ‘ettztTesazed ‘eTTsTesoTo ‘eTtzytuedo - 
oqdt To /eTta deszed 


HINGOW LYOddNS ASUVdddI TWAINAS 
p*zeyoed zoz queweoeTdez zeTquesse s,TINH PTezeD “2G use’ yorde 
Buttoko zoToo peseq ydnzzequtT xoZ euTQNorA s,eATTS ued o-qaoko 
preogdtTS worz/oz LXLd JO Huyddyto ATduts seqerysuoueg IXLAIT TO 
watr Aue qnoqe ogsut [Tnyesn Ano sjuTId 
(agasmwa sesn) eTTz aagI Aue zo out Tqno squTazd pue syxeyD 


(seTnpowu ou eaztnbez pue ATqpeatp Azezqtyt‘eszedzzt esn) SAIANYXA UAHLO 


AWGVAHY'SPINPOW dal 





: Source Code 491 


IFF Specification 


(oSdaw)$ (SOWIdT)$ (sdaw)$ O- UT 
(osdaw)$ = (saaw)$ 


(opdaw)$ (SOWTaT)$ (vddw)$ O- UT 
(opdaw)$ +: (pddw)$ 


(o€daw)$ (SOWIaT)$ (€ddv)$ O- UT 
(o€dadw)$ =: (€daw)$ 


(ozdaw)$ (SOWTaT)$ (Zddv)$ O- UT 
(ozdaw) $ = (Zdaw)$ 


(otady)$ (SOWIaT)$ (Tddw)$ O- UT 
(otdaw)$ = (Tadw) $ 


uofpqeottdde yoee zoz efexutT # 


(dav) $ (Lddv)$ (9dav)$ (Sdav)$ (pdav)$ (cdaw)$ (Zdav)$ (Taay)$ :TTe 
suoTqeottdde ey3 JO TTe exeW # use's$ (SOWIdW)$ (NWSW) $ 
ro‘use- 


tT" use’ y" O° :SaxIagas" D'a$ (SOWTAD)$ (95)$ 
:S3XIaans* 


osday > 
OLdayw (sOWI4T)$ (8ddv)$ OL 


o9day (SAI'TAW) $ QTT“eHtwe:gIT QTT°OT-QTT AUWUAIT 
osdaw (ogddw)$ O75: qTT Woud 
ovday > HLIM> xUTTq 

orday (osddy)$ = (sdaw)$ 


(OMNGII)$ (OSNETII)$ (OTNATI)$ (OMNMII)S (O44I)$ O° (GddW) S$ 
(OMNAII)$ (O44I)$ 0° (Laa¥) $ 
(OMNETII)$ (OF4I)$ O° (QdaY)$ 
(OIWHTI)$ (OWNETI)S (O44I)$ O° (SddY)$ 
o*oqutaduq (Ww) $ (OMWHII)$ (OUNBTI)S (OF4I)$ O° (Yddw)$ 
(Od4I)$ O° (Eddw)$ 
(OSWEII)$ (OTWATI)S (OUNETI)S (ORI) S$ O° (ZdaW)S ozday 

o*syunyoddoo (nN) $ o*dumpueezos (N)$ (OWATI)$ O° (Tddv)$ = OTddv > 
etduexe uotqeotTdde yore Aq pepeseu setnpou yo0efqo euL # (SOWIgl)$ (Laav)$ O12 
(SAI'TAN) $ QTT ebtwe:gIT QTT°OT?4TT AMWUEIT 
sdqyv (OLddv)$ O° D>: qTT WOud 

Laayv > HLIM> AUTT 
9aav (OLdd¥)$ = (Laaw)$ 


sddw 


vddw > 
eddy (soWIaT)$ (9ddv)$ O% 


PEOTNETI/PEOTNETI (w) $ cdaqw (SITAW)$ ATT ebyuwe:aqrT ATT OT: qt T AWWuaIT 
oweqwa TI /oweqWaTI(w)$ = TddWv (o9ddw)$ O°: qQTT WOoud 


suotzeottdde eszedzzt xno # ‘ > a ee 
o9ddw. > (9ddwv. 


oued3tqpz/oued3tqyz (uw) $ 
WHTIOIMEY /WATIOWMEN (W) $ 
SAReguEEIDS /eAeguEEIDS (Y) $ 
MEYOWNATI/MEAOINATI (YW) $ 
DOAWETII/OOIWETI (w) $ 
xaseheta/xaseheta (w) $ 


OWaLXa 


OWWTI > 
OMWa'II (sOwIgT)$ (Gdd¥)$ O72 


OTAGII (SAITAW) $ GFT’ ebrwe:a@IT QATT°OT:QTT AUWUAIT 

Osna TI (OSddv)$ O°D:qTT Noud 
o*zexoedun (WM) $ O° TUqTT (HK) $ Oana TI > HLIM> AUTTA 

0° 00H (W) $ o*eszed (HW) $ OaaI (oSdaw)$ + (sddw)$ 

UTM YAUTT OF seTnpou Aoefqo qzoddns eszedyzzt ano # 


ooqutTaduq (Ww) $ o*dumpusexzos (Ww) ¢ O° syungqoAdod (KR) $ 
(OMMETI)$ (OSWEHII)$ (OTWETI)$ (OUNATI)$ (O44I)$ 
o-zexoed (W)$ O*MMTT (W)$ O'UqTTEARS (HN) $ 

o* dew37q305 (nN) $ oO WqTTPeOT (W) $ 

o*ue9ezos (W) $ O° AetTdstpjeb (W) $ 


vinnie 


> 
/sdde (sowlal)$ (pydaw)$ O- 
/s®@TRpou (SAI'TAW) $ QTT"eHtwe:aIT ATT “OT: QtT AUWuaIT 
(Opdd¥)$ O°O:qTT Nous 

> HLIM> AUTTQ 
(opddy)$ +: (vad) $ 


OpnypouTxXuew: xTOMI- 


> 

(sOWIaT)$ (edad) $ OF 

(SAITAW) $ ATT" ebtwe:gIT QTT“OT?GQTT AUWHAIT 
(O€ddv)$ O'S: QTT WONT 


att’ Snqep:gIT =sal TAN# > HLIM> XUTTq 
(o€ddu)$ : (€dav)$ 


XUBIN S|1JOHeW SVSSINexeW 





Devices 


492 ROM Kernel Reference Manual 


/~ ‘oweu s,zoyqne eyQ ‘[]wwHO & sutequoD yunyo HIAW 


[anna anna n= -- === wa-n------ 


/x “9O0T {Ou aqeyaidoe 5 WHOS ey ‘[]awHD & sutequod yunYyo , (9) " 
/4--------- ---------- qWbrxhdoo 


“eueU Ss ,8DTOA SeYyQ ‘Ciawno eB Sureadoo yUnYyoO FUN 


izepeepgeoton { 


‘ehuez opueudp s,erempzey qndqno eyQ » 
ojuyt entTea styy dew “(eumToa TINZ) » 
Katun 09 09 wozz eumtoa Teutuou yoeqhetd x/ JOEUMTOA PeXT TI 
/»+ pesn enbytuyoe 3 uotsseazduop eqep »/ Juopssezdwoos 
/% SWIOFCAREM JO SEABQDO JO # x/ 7eAB4D039 ALAA 
/» © 3ex Suytdues eqep »/ {pegzegsetdues miomn 
/+ 0 esTe ‘eaeqno ySTy uy eToAD/setdures # x/ JetoXkotHzeaseTdues 
/*« 32ed 3eedez eaegqno ySty eq3 ut seTdues # x/ ‘setduestyyeedex 
/« 32ed QoYs-T eaeQoo ySty eyR ut setdues # x/ ‘setdurestH3oyseuo SNOTN 
} qonzqs yepedAq 
/* "S8INANZ CYR UT sputy ero eq PTNCD x/ 
/x (D x}¥pueddy) BHbutpooue eqTep-fooeucgdT” »/ t eareaqtadups eutyep# 
/* pessexzduon jou »/ ° euondups eutzep# 
/» "seTdues ey3 03 pettdde uyqtzobte uozssezduop Jo eojtoyD :uctTsserduoos »/ 


/» SUMTOA uMuTXeU = O°T pexta = Aatun «/ To00COTXO Aatun sutzepH 

/x “SUA9ESGD “OT ‘SUAZTe¥z FO Toqumu » 

e st pexta w “3yhTr eyQ OF 9T pue QuTod oy + 
FO AFET SYR OF SATQ 9T ‘onTeA QuTod-pexTz VW x/ /pexta ONOT szopedsy 
TSPSSOHBSOTOA —---------- x/ 


= a /* 
‘,@,)aI_DIw KGO@_GI euTyepH 
1.) OT_aaWW ONNY_GI eutszep# 
,) CI_SWn HLOW_GI eutyop# 
1) )GI_aNWN 346trAdoD_ar eutzep# 
iN.) aI SUYW WYN GI eutsep# 
ysFt/AZFT UT poeutsep +/ 


7a.) 0I_SauN 3STa_dI eutzep# 
al IW WVLN I eutszep# 


+h.) OI_SaYA MAHA_GI eutzep# 
‘,8,)aI IW XAS8 CI SUTsFEPH 


wt STF/ITTTu OPNTOUTH 
FTpuc# 

wY ToT Fduoo/dzzZT, Opntouty 
H UMILaWOD FOpust# 


H_XASLHSIG eutyep# 
H XASLHDIZ Jepurt# 


* zeqnduoo eB yuy_ezopoumo eYQ TOF uotszrea sTUL 
WHO SWD - 16/SO AzeaqtTeszedzzt YRTM ESN TOF PEeTSTPOW 


‘ufeuop oftqnd ey3 ut st eTeMAZOS sSTUL 
“sqzyw otuoz3q0eTq ‘seXeq eaeqs pue uostzzow Aazzec Ag 


KK RK KK KK 


98/0T/Z * (KOA) SD FOA Reroers ats zoz euorarersed H*XAS8 


poco ee 


UXAS8/Gs}I 


use*x$ Og O- (SOWLaY)$ s® 


D'a$ O'x$ O- (SOWIAID)$ 99 


atr-ebture [T+ OT- (osddy¥)$ (sowlal)$ (sddv)$ O- UT 
(osddw) $ 


art ebture [T+ OT- (OLddu)$ (sowlal)$ (Lddw)$ O- UT 
(oLday) $ 


att‘ ebtwe T+ oT- (o9dd¥)$ (sOWIAT)$ (9ddv)$ O- UT 
(o9daw) $ 


XUBIN 8/4 


:o°use’ 


: (8daw) $ 


> (Laaw)$ 


2 (9ddu)$ 





: Source Code 493 


IFF Specification 


sTpue# 


JesegeszegaaiIx AzerqyT qonzy4s uz93qxe 
/* seTnpou Aq peouezezez ,/ 


‘ 
Hf 
/» 9zeq setTqetzea ppe Kew suotyqeotitddy x/ 


/* MoU TOF O OE Asnu ,x/ ‘(g] peazesey ONOTO 
‘[Log] eweu aLAGA 


‘ (Looxun] sokods ONO 
‘ [LOOXYN] sez tsz ©NoTn 
‘ [LOOxWN] sdureszy aLAG 
‘ [LOOxUN] sez Ts0 ©NoTOA 
‘ (LOOxUN] sduresoy ALA 


‘seqiqoeTdues SNOTN 
Je Tdures, FLAG 


/zPTA TSpeoRgedoton 
/=« XAS8 x/ 
/* 
(petdod ueeq eaey syungo eq ZF ()XUNYOpuTy ZO)» 
()dozaputa ybnozy3 etqtsseoDe eq [TTTM syuNYo zeqIO »* 
‘eTdues pue ‘eueN ‘YdHA OF sseDDe AUeTUeATOD I0g x/ 


foguyeszeg osujeszeg jonz 7s 
/* peqetez o-esized ~exeueb ,/ 
} oxurxasaqbta yonz3s 


91 LOOXYN euTzepH 
<qY°OTpne/seDtaep> epnTout# 
oY xasg/dzzT,, Opnpout# 


H_ddWXASLHSIA eutsep# 

H ddWXASLHOIZ ae 

* 

BsUCT{TUTJFEp OFF Toeds-uopjeottdde - 

uotzeotidde pue setnpow Aq pepeeu sepntTout JO uotsnTouT - » 
ernqzonzys osurTKXASayhta FO uoTATUTFEep - » 
y'ddexasg x/ 


y-ddexasg/dyji 


sTpuc# 
(2PHA( LAG) ‘(TepeeH_eDtoA)Foezts ‘YGHA GI ‘FFTt) AOIna 
\ (2pPH4 ‘FFT)UGHAINA SUTZEPHF 
/x "“AUNYO AGHA & O3TIM OF OTOeUW sTYR TTeSD 3snL «/ 
[armen nn seutqnoy yzoddns ze 31T2m xXASB 


/« (L@T ySnozyA gzt- ‘szequmu peubts 3Tq-8) x/ 
/+ ‘se tdures eqep otpne so Aezze ‘[]aLxAq © sutequod yunYyo xGOE x/ 


*ZTOPeOPESEOTOA SYA UT peTsToOeds oumToA TeuTuUOU eYQ EeTeDS OF pesN §,3I x 
‘sentea pextga Bbupurnjez suzy Jo uoTAouns e seutTzep edojTeaue syL »/ 


/» ‘edoTeaus rzeeut{T-estMesetd ‘[]jutog5g ue ufequod syunYyo aSTY pue WLY +/ 
‘qutodod { 
/x ZOYF oumypoa uoypAeuTAsep y/ qsep pexta 
/* 0 < ‘SpuoDesTITTu uy uofTAeinp queuhes ,/ ‘uoTqeaznp qiomo 
} qonz3s zepedxq 
/arccr en eS eR aH RE Reena SSeS gsTa 3 Waly edoTeaug 


/* ‘suoTzeqouue 4x83 s,zoyqne eyQ ‘[]UWHO & suTequoD yUNYO ONNY +/ 


U"XAS8/G434I 





vices 


: De 


494 ROM Kernel Reference Manual. 


H UAIIGWOD FTPuS# 


= /s 
SOLOUd ON SUTFEPH 
x/ 


sFTpue# 
u{’ sedXq/oexe, epnTouT# 
H SdAL OAXT FOPUTTH 


(0A UUUUUGOUUUOUUUUORUB BUBB UOUR BREE EEE / 
/* WHD SWO - eszedzzt yATM ESN TOF 16/GO PETITPOW »/ 
/* ‘utewop ofTqnd ey3 uy st exeMazos STUL x/ 


* 

in *setsezouXsoTpy zeTTduop etTpuey 03 eTTZ AatTTqeqzod 

/* 98/62/T meys 9003s 

UMA AHA HARMAN RR EE Yr TeTTdwoD xxx/ 
H_UPIIANOD eutzopH 
H MATIGNOD FOpustH 


Ysa|lawWi09/ajyI 


n¥ Snqep/dz3T., 


<q" butz3s> 
<YOTpys> 
<U°QTTp3s> 


<y'soj0rd_eszedgzt/qtto> 
<y°soqoiad sotydez6/qtto> 
<u" soqozd vot atnaqut/qtTo> 
<q" soqozd sop/qtto> 
<y*soqozd pexe/qTTo> 


<y‘oszedzst/setrerqt{[> 


<y* sozoeums6/sotyderb> 
<Y" Torquoscepta/sotyderb6> 
<yosutketdstp/soryderb> 
<y"moeta/sotyderb> 


<Y" sueerDs /UOTATNAUT> 
<Y UOTATNQUT/UOTATNAQUT> 


<Y" sop/seTtzezqtt> 
<Y" seTzeIqTT/Sexe> 
<y° Azoureu/oexe> 
<y* sedk3/oexe> 


H_WDIWY 
H YOINY 


yTpuey 
opnpout# 


opntout# 
epnpout# 
aepnTout#F 


epnTout# 
epntout# 
epnTout# 
epntout# 
epnTout# 


epntout# 
epnTout# 
epnrTout# 
epntout# 
epntout# 


opnpTout# 
epnpout# 


epnToutT# 
epnTout# 
epntout# 
epnpout# 


ouTsopH 
FOpus tt 


/* 


SeTTF epntout uotqeottdde gar x 


yediwie/ajyl 





IFF Specification: Source Code 495 


/» H SNaaaxW x/ FTpue¢ 


sTpue¥ 

¢ (x)adq eutzop# 

‘ (%)zq eutzopy 

‘ (x)daq eutzep# 

¢ (%)qd eutzepy 

/* ZO peurny Bbuyhhbngep Teaet 3Asrztd «/ esTe# 

/« @THAR TONGA «/ FTPUS# 

‘ (x) 7a eutzepy 

‘ (%)zaq eutzepy 

i (%)Za eutzep# 

/* 33° peurny BHuyhhbnqep jTeaeT puoses ,/ esTo# 

(x) (x) Za euTzepH 

(xwrgapnqgad) Aeted ‘ (x) (x) zaq eutsep# 

(xwiaapnaga) Aeteq (0<AWTaaDnGaa) FF ‘(x) (x) 7a SuTzFOp# 
/« 5azbbaqep Tease, puodes uo urn, »/ 7TaAATTONGAC STH 
(x) (x)8aq eutzepH 

(awraapnagad) Aeted ‘ (x) (x)aq eutszepy 

(awraapogaa) AetTed (o<AwTaaondad) st * (=) (x)a euTzopH 
/x 5azbh5nqep TeaeT 3sztF wo wrnL »/ SOAAGAW 3TH 

/x 

Sutbhnqep TEAST pucDdes ore soueu TFeEqQ UT 72. AIIM SOTOeW TET TUTS eo"uL x 
s Ut ‘seTqestp’sptqzoz ut esq ‘Aeteq sesn xeaeu (xDTNb Haqep) )6nq)da « 
xAwigapnagaa sXejtep skenye )5nq)aa » 

oO < 8} xwIaaonaadq 3+ AwTaaonaaa sfeTep ybnq)a x/ 


/* 


sozoew B5utbbnqeq » 


a/ 


sTpuey 

zazutazad bnq eutzepH 

/« 8,3707I1d 03 8,6nq [Te sebueyo este y/ esTo¢ 
F.uyzdp Snq eutzep# 

onagad sTTe# 

yz utyzdy buq eutzep# 

onaaa Ft# 


/* 
zautadp zo ‘z3utzdy ‘zquTazd 03 jes ATeotpQeuogne uot jounz Hbuybhnqed » 
«/ 


/ 

“butbbaugep Tetrezed zoz qtTT“Snqepp y3TM AUTT pue T OF Onagad es 
“buthSnqgep Tetzes rox qtT’Snqep yATM AUTT pue T OF OnaIai eS 

squeuejeqjs SuthbhSngep (zd) TeaeT puoDses uo uwrzng OF OTeEZUOU ZTAATTIONAI 3°S 
‘peztsep st Aetep e ueym (0g “x8) SYOTZ JO # OTez-uoU e 03 AWIaGNNGSd 3°S 
reaoge yes suotqdo zesn 


* 


*BbupSingep zyo urzng 03 eTTduoDez pue 9 073 Yes) “Snqep of ystm nok 
se@TRpow eyQ eTTdwopez pue pexztsep st Bbuthhnqep ueym [T of eACge ONAAGAW 2°S 


£((nU\2xxX Op 03 Qnoqy,,) nq) aq 

‘ ((eTqetzeahur’,,u\xTs$ = eTqeTzea :yAseqqns uT,,) 5nq)da 

1 ((ea’Za’TA’,U\XTS$=EA XTS$=ZA XTS$=TA,,) 6nq) za 
‘((oTqetzeadur’,,u\xTs$ = eTqeTrea “zAx op 03 ynoqe,,)5nq)q 
(ewes eYQ pesn exe TTe) sesn oTduexe oeuos 


(qadnzxzeqjur zo ‘ysey 

‘eTqesta ‘ptqzog e eptsut BbuthSnqep -et) zeqze Aetep e quem YAN TT Nod 
3eq3 ButShinqep xox (()5nq)dq pue ‘Aetep e Aq pemoTtTozs quem sXemte nok 
qeyqq squewejeqs Burbbnqep z0z (()5nq)qq ‘ees oj peeu 3,uom AtTensn nok 
3eyq 5ut6Snqep exz3xe z0z (()6nq) za ‘Hbutf6S5nqep Tezeueb xoz (()Snq)q esn 


Kee KK RK KKK KKK KEK KR RK KK K 


Oxez-uOM ST ONAGGAW JT Spood oqezeueh Atuo (()6nq))3a ’(()5nq)za ‘(()Snq)a 


* 
~ 


(°° * ‘quzy BLxdn)F3IUtzdp ptoa 
Cams g TEnaa) sanrzdx PToOA 
<q soqozrd sop/qt{T=> epntout# 
/« “Ysuopqounz ro y*sop/ojorzd esn 29 “s3utAzdp ‘zquTzdy ‘AeTeq z0z sedXkj0R07g x/ 


‘ 
s 


/* ONGIAGAN «/ FTPue# 


0 Ondzdd euTzep#F 
/« (Q¥T Saqepp q3T yuTT) SurbhSnqep TeTTered z0z T 03 30S ¥/ 


0 Onegai eutzep# 
/* (QtT°Saqep yy yUTT) burbbaqep Tetzes roxy T 073 20S ¥/ 


os AWIgaonagdd eutzop# 
/* sozoew xaqd ey xX0Z oxez-uou skemty x/ 


0 AVTadoadad SeuTsepH 
/+ ebesseu Baqep yore zeqze pequem st Kejep e& JF syOTZ FO # OTEZ-uou e& OF WES x/ 


Tt TTIATTIONGIA SutsopH 
/x SQueue{e4s (()5nq) zq TeaeT puoDves urnQ OF T O23 20S ¥/ 


/* 
suotjdo zesn SNGAdAW + 
a/ 


OnagaaAW FT# 


0 SNeAdAW eUTFOPH 


H_DNAGAW SUTFOPH 
H OnGaGAW Fopust# 


/* 

buybbaqep sFo urny 07 9 ‘butShnqep wo ung OF T O23 ONAAGAW 30S +» 
YOTPAs TSAZe eu jeuos ETTF sty epntouT# - y~Snqepéu S 

* 





vices 


: De 


496 ROM Kernel Reference Manual 


‘ (DNOT) Tz07gI*% ALAA 

i (4 STPURHAII YONIQS)OTPAsseZTTATUT PTA 

i(pt ONOT ‘odAQ ONOT ‘334% OTPUCHAAI JONTAs) e3epdozdputsy ALAWO 
(pt ONOT ‘edXkQ ONOT ‘x STPUBHAII QONIQsS) STAXeGQUOD ONOT 


‘(Pt ONOT ‘odAQ ONOT ‘s STPUBHZIT JONIFS) spyUNYoQueTIND SNOT: 


i (, STPURHZII QONTYs) AxeZUODRXeW ONOT 
£(, STPUeRaII JONTZs) yxeQU0DReS ONOT 
‘(x SNOT ‘x SNOT ‘x ONOT ‘SNOT ‘SNOT 
‘y ogureszeg 3onzr3s) eTTFFeszed ONOT 
i (4 OFUTESTe_ AONIAS) OTTFTEsOTO pToa 
/(ONOTO’» ALAGO’s» OFULESTeZ QoONTRs)eTTZTUedo ONOT 
/x_o°eszed 4/ 
SOLOUd ON FOPUTTH 


feqed qx PToa 
sezts yo Suot 
‘ar_yo Buot 
ma Buot 
qonz38 
} yUaYD FoNnzAQs 
/* 
syuny> JO AstT pexutrT Atbuts e seed zo eaes 03 seTnpouw euos Aq pesn » 
a/ 


{ 
‘[g] peazesoy SNOTO 


isyunqomeu, yung jonz4s 

/* 

‘eurezy eyR YITM AF desy o9 aenf ~ 

ezey syuny> meu FO AsTT uMO sQq Suey Aew uot jeoytdde x/ 


ésyunyopetdos, yunqo 3onz4s 

/s 

()astTyunqoeezzy Aq peqeooTteed + 

‘etts SuysoT> z9eqze punoze , 

osut yunyo peszed decoy oj peeu 3eqQ swexhord pue » 
suezbord eqtam/Asypou/peez zoz - o*syunyokdod rox x/ 


/* MOU XOJ oreZ eq AsnU /Tpeazesey ood 
/* STTZ xeTdmos e Sutsxzed eze om équnq 'Ioog 
/« pxzeoqdytTo st eTTZ ipzeoqdt To oom 
/*x peuedo useeq sey J3T STUF ‘peuedo ‘Too 
/« (XGO@ SXFT) SseqQ uo doqs isxqodoqs, SNOT 
/* 3ETTOD 03 setyzedoad {SYYOIOOT TOD» SNOT 
/+ 385 03 setazedoid ésyqodozd, SNOT 
/=x FQ sty FO ouweueTTF Yuerrnod ‘emeueT Ts x aLAan 
/* JAIOOTTN FFA P,OOTTe eq oF ‘33FTx STPUCHAAI  JONTAS 
/» pe,etTez o‘eszed Tezeueb ,/ 

} ogureszeg QoOnz48 

/* 

“seTnpow etduexe eyq Aq pesn eznjonzy4s osutT oTzFToOeds-uI0J 

Azeae zo Sutuutbeq ey UT pepnTouy st erNQONIzAS STUL « 

‘pqe ‘syunqo petdoo ‘eueuetTy ‘j0u z0 pzeoqdtToO » 

8S} STTJ TeYQeYM pue ‘ETpUeHAIT peqeooTTe Jo yorzy deex o3 pesn x/ 


(1%1/10,',0,/ @-) Ol_SaWA XGOG_dI eutzep# 
(.0,'sX%.'.3,' .b,) aT_aawWM IXaL_dI eutyep# 
(3.0...) QI_DIW outzep# 
(0800804 As 1d) OT_ DI eutzop#e 
(.6,/,9,',8.'.0.)Q1_aiwW LaSO_dI eutyop# 
(, 0 2'2(4',34'.),)0I DI aqbtazkdop aI eutyep} 











(18.4 08./.H,/.0,)0T_ WN SUHO_AI eutsep} 
(1H. ahs! 0,’ Nt.) 01 DIM HLAY_AI eutsop}# 
(40,/.N,'.N,'.M,)dI DIM ONNY GI eUtTzep# 

/x xe QUNODUS Kew om 8,0I YUNYD oTTeuey ,/ 





Z utad efbesseu eutyep# 





qs _STIAGON SUtsop# 
It UOWMUA LNAITO eutzop# 
TO AWIO JII SuTzFopH 


_(T 3 ®) (&)ado sI euTzep# 


(ueog uo<-uo - 8ZTg «ud<-uUDd) (up) seqXkgezoyyunyo eutzep# 
{/(uotssezdxe) = zozze (z0x270e;) FT} (uofssezdxe) zzgxD eUTFEpH 











FTpuc# 
((%) = (%)- € 0 > (%)) (x) saw eutzop# 
say yopust# 

FTpusez 

(a) > (e)) (q’/2) NIW eUTsFEpF 
NIW Jopust# 

FTPus# 

(q) < (e)) (4/8) XWW OUTFOPF 
XUN FOpuUsTF 





((q) = (e) 


Oo 


((aq) = (e) 


oO 





FTPUo# 
<q" sojord eszedsyst/QtTO> epntout# 

<q" soqord | DEXE/QTTO> epnTout# 
SOLOUd ON FOpUrT# 





FTpusy 
nq Snqep/dzztn epntout# 
H ON@AaAW FOpurT# 





<q" Sutzys> epntout# 
<U°QFTPIAS> OpnTout# 
<Y°OTpys> epnTout# 





sTpue# 
<q" eszedzst. /SOtACIQTT> epnpout# 
H GSuvdddl SATIWAEIT FOPusTH 
sTpucey 

<4" syooy/AQTTT3N> epnTout# 

H SHOOH ALITIEN FOPUSTH 

FTpuc# 

<q'westhea/A3tTt3n> epnTour# 

H WALIOVL ALITIIN FOpust# 
FTpus# 

<q" Azoureu/oexe> opnTout# 

H XYOWEN OAXA FOPUTT#H 

FTpue# 

<y*sedk3/oexe> epntTout# 

H SAdAL O9Xa FOPUTTH 


uY TeTyduoo/dyzt, Opnrout#y 





H_daI_aiaI eutzop# 
H ddI dddI FOpurt# 


/* 
T6/LZ/9 * 

-” 

seTRpou oesieggIsI TOF suofytuTpyzeqd TezeueDH *USTF x 
* 


«/ 





IFF Specification: Source Code 497 


= bs (spwLaava~ 
(OAGIA MOOINTD|OIGAY WOOINES|AGIH 4AlsSaLTuas) 


) MSWNONWOCIO eutTsepF 


SOWLIGWE SUTTEpF 


/s 


PETPPTAR Sq ROU PTNoYs s3tq (prom YSTY OreZ-UOM) PT Epo ATq-ZE EUR SION + 
“esn IO EARS ETOFE OWWD 3TI-9T PTO FO Jno pexseu oq prnoys yeyR shea x/ 


(vy >> ¥ << GT + (m)) 
(T >> » << ST + (M)) 


(a) Moyzegsata euTFEpH 
(4) moyzegseqig eutyep# 
/» MogxegsezAg 03 YAPTA ArEATOD »/ 


V2 HLdACaAYSXWN SUTTEPF 


/» eaes UBD OM soueTd umUTXEW x/ 


ZE OMMIOTIOONVXWN SUTFOPH 
8 HLdaGNYXYW SUTFJOPH 
/» erNQONIASs dewatd uy eTqezoyjs seueTdatq Jo zequmu umnwyTxey »/ 


/x"S3TQ ZT MOT UT GOW YORO BITq FY TITA » 
‘pxz0ToD auom zepedsy 


4xeqstbez-zoToD e Jo uotszea Wwa ebtuy »/ 


€ zeqsTbeyzoTopszoezts eutzepH 
/x * (t0q4sTbeyzoTOCD) yoezTs FO peeqsuy QueqsuOD sTyQ es x/ 


(.9,/ UW.‘ WW.'.D0,) aT_DIWN 
(.0./.8,'.4,' 0.) 0I_ DIM 
(ib, 8,'.4,',8,)0T_ DIN 
(,8./0,' 8,‘ .9.)a1_ IW 
(.0,/ 08,419. ,9,.)0T_ IW 
(.9,/0N,/ 8,'.9,)01_ Saw 
(.4,/..' 0,’ ,D,) aI DW 
(.4,°,8.' WW.’ @.)aI DW 


SWWO_dI 
LSaq_aI 
iaas_ar 
awa_dar 
Io0_aI 
ONIO_AI 
avwo_dI 
GuWa aI 


(syunyD ofFreueh zeyRo eulOos TOZ YW SFT/AITT 
zeqjunooue Aew em s,qI yunyD 


CW,'.@,',T,’.1,)00 DW 


WHII aI 


/*x zequnooue Aew em sedXkq 


outzop# 
eutTsepH 
eutyep# 
eutyop# 
eutTsopH 
eutzepy 
eutzop}H 


SoutsepH 
ddI x/ 


FTpusH 


<y°soj0zd qtTe/qtio> epntTout# 
<q" sojord woT3tnqut/qtio> epnTout# 
<y' sojozd_ sotydezb/qtTo> epntout# 


soLodd ON 


FOPUTTH 


FTPuoF 


<y* Toxzquovoepta/sotydezb> epnTout# 
H TIOULNOOOAGIA SOIHUWED FOPUTTH 


FTpus# 


<YUOFZTNQUT/MOFAPAQUT> SpNToUT}# 
H NOILININI NOILIOLNI Jopurst# 


“xepeer WATI SsreddiI TOF suoTaTuTszed 


Yywig]!/ayl 


TTpuse¢ 


ot FZT/AZFTn OPNTOUTH 


H ddI dddI 


H_WATI_ daar 
H WHII dad 


FOpust# 


eoutsop# 
FOpust# 


/s 


T6/LZ/9 x 


7a" 


watt 


/« H dal daaI x/ FTPUSP 


/* SOLOUd ON «/ FTpPuSH 
2(4sztse MBNYD AONTAS 'FFFx STPUCHAAI 3ONT3s) QeTTAUNYoOeWTIM Huot 
(pt Buoy ‘edXy Huot ‘Aszzz, YUNYD AonTAs) XuUNYOpuTs, YuNYD Wonz36 
/(asztz~ YaNGD 3ONnz3s) QsTTAUNYOeerz PToa 

/ (edXqueu SNOTN ‘sxYROETTOO”’ SNOT ‘sxyodordy SNOT 
‘J3Tx OTPUeHAAI QONIQSs) syunqoAdoo, YunyD Aonz3s 
/s ao syunyokdoo ./ 


f(eqep, ptoa ‘ezts Huot ‘py Huot ‘FFF STPURHAAI QONTRS) YO ng Huot 
I (4 SNOT) 3UDAYO ONOT 





vices 


De 


498 ROM Kernel Reference Manual. 


(4 OFUIWATI 2OnzQ48) XeTdstpeyetep pros 

2 (4 OJUIWETII AOnITQ8s) Aetdstpeyeez> SNOT 

2 (WQTTs OFJUIWETI QONTAsS)wqTFMOYSsUN PToA 

‘(eureueTTS*% ALAGN ‘WATT* OCFJUIWATI 3ONIAS)WqTTACYS SNOT 
/x (Ketdstp e peot oj pesn) oAetdstpqjeb x/ 


‘(@zysznq ONOT ‘TEFFNGe ALAC 
‘zpHuq, xzepee_qdey{ta ‘xseuy ALA 
‘dewatq, dewata 30nz39 ‘337% eTpue_aaI QOnTQ8) Apoqand Suot 
{(unBzedsatq GaoMaA’sz0TOOU CUOMNETIEATOTOO ULdW‘FFtx STPUCHAAI 30Nz38)deumgjnd buoy 
! (pyepou ONOTA 
‘qqbyepebed auom ‘qaptmebed quom ‘3q5teq qaom ‘TIPTA aYuOM 
4‘zoTODquezedsuez3 GUoM ‘uoTssezdmo> quom ‘Sutxseu CUOM 
‘dewatqs dewata 3onz3s ‘pywq, zepeeqdenqta) pumqatut BSuot 
/» 89UTANOT TOQFIM WATI OO MUQTT »/ 


2 (W@qTT* OFJUINATI 30nr38) bureo30e6 SNOTO 

{ (WqTtx OFUINATI 3ONIAs) OTGeATOTOOOOTTE ONOT 

/(WQTTs OFUIWATI 2ONnzrQAs) srOTODeEEeIZZ PToA 

/(WQTTs OFJUWIWATI 3ONTAs) sOTOCDACH ONOT 

J (sz0TOONds TYOHSN ‘STQeITOTOD, GYOM ‘x STPUPHAEI 3OnrT38s)deuppeotT ONOT 
/(@ztsznq ONOTO ‘TOFFNGy FLAG 
‘pyuq, zepeoHdenata ‘xseuy ALAC 

‘dewatqy dewata 30nr3s ‘33}*% STPUPHAAI QONT3s) ZApoqpeoT ONOT 
‘(pquq, zepeoqdenata 

‘deujtq, dewata qonz3s ‘’s34* STPUeHaaI 3OnzQ8) Apoqpeot SNOT 

/* SEUFANOT Tepeexr WATI O'TWQTT +/ 


/(@zTsMozr ONOT ‘38eddyx BLAG ‘eornosdyy ALAG) MorxOed ONOT 
[x o°z0eyoed y/ 


‘(oseakaasp miom ‘oseqkgorzs qaom ‘3seddyx abAd ‘eornosdy» FLAG) moryOedun Too 
/* D*zeyoedun x/ 


SOLOUd ON FOPUTTH 


(9299 (4 ALAG) ’ (WUNYOITDD) Foezts ‘TOD GI ‘FF4) AOInd 
\ (ard ‘ZZT) Q2D0And eutzep# 
(6uz9 (x FLAG) ’ (ebueyd) Foezts ‘ONYD AI ‘FFt) AOI 
\ (Suazo ‘33z7) Buzoqnd eutzep# 
(ues (, gixa) ‘ (yUnyoburep) Foezts ‘OWWO GI ‘3FT)AOINA 
\ (Sure ‘337) Sareoqnd eutzep# 
(pezgeqtads(» aLxa) ‘ (eouepevezgeqtads)zoezts ‘Iuds aI ‘334)AOINd 
\ (pezaeaqtads ‘3z34)  q2dsqnd eutzep} 
(ebzenjsep(, aLzd) ‘(ebzewajseq)zoezts ‘Lsad GI ‘3FT) AOI 
\ (ebzenqsep ‘37ZT)asepagnd eutzep# 
(azqutod(, azza) ‘(az3utod)zoezts ‘awud dI ‘3FF) AOI 
\. (azautod ‘33t) qezband eutzop# 
(zpHurq(» aLxa) ‘(zepeeydenata)soezts ‘aHWa GI ‘33+) 4AO3nd 
\ (apHwq /334) puwqand ree 
* 
“syungo eTduys esey3 roy sore eseyR esn ued nod x 
‘pueq Aq syunyo aznoX zo TTe buyytazm exe nok FI »/ 


fyunyqowe) { 

/» ©zeq 9 ez0R8 - dxe eznqnz x/ ‘ped qauiom 

/+ BuyTOAD ueemjeq soesu ,/ ‘spuodesorTDTU ONOT 

/» ButToks weemjeq spuopes ,/ ispuooes SNOT 

/» xeddn ebuexz ,/ /pue gLxAGn 

/» Xemot ebuex y/ ‘qzeqs gixzqo 

/= spzemyoeq=t- ‘pzemzoz=T ‘eToAD 3,U0p=0 x/ ‘uoT_DeITP CuOM 
} qonzqs zepedA3 
/* “AUNQ TBOD & UF pez0js sft 3700 W +/ 
yunyo buttoxo (agzezoqzyderD) 3700 »/ 


/x peqoetes szeqstbexr zroToo zeddn pue zemMoT «/ fq6tq ‘molt aLxGO 


Ywig|l/ay}i 


7eaTtqoe 6CIOM 
7e3ez COM 
‘tped qaiom 
} qonzQ4s zepedsQ 
/* “ORY ONUD & UF er0Rs sT_ebueYyo Ww +/ 
/* PAFWOe-UOU Uwe OF EVET sty sesn qutedd »/ 9€ ALWION ONY CuTyop# 
yunyo ButToko ebueyo 


/x« S8T0AST = 2O8 T AT ‘@ATQOe = 208 09T +/ 
/*= €LZ7=09/P8E9T=O88/T ‘Z6T8=9E8/0E ‘PBE9T=9E8/09 +/ 
/* SEY QO eT0Qs ‘/esN EINANZ TOF peazesex ,/ 


fyunyoburep { 
7 S@pONMETA SONOTO 
} qonzq8 zepedxy 
/x “ONOT © SB pezeToOep st QuequUOD s,xXUNYS SUL +/ 
/*« "%UNY OMYD & UF pez0js st sepow<-—jiogmetA ebyuy eropoum0D Y +/ 
epow qzodmet, ebtun Sued 


Jepuepevezgeqtads auomn jzepedky 
/* "AWNY Tuds & UT pexojs st eouepecsezgeqtids Ww +/ 
epuepesezgeytads 


‘ebzenqseq { 
‘yseweuetd quomn 
‘ZFouoeuetTd quoman 
‘yotgeuetd quomn 
‘tTped anxan 
‘qqdep ganxGn 
} qonzqs zepedxz 
/* “UNS LSA & UT pezoyjs st ebzepysed YW x/ 

ebzennseq 


/x OAT Ez0Rs 03 seUeTdATC YOTYM sqoeTeEs ,/ 

/* yptaeuetd zoz ejep eueTdytq arneszep »/ 

/x UOTAeUTAsSep OUT seUeTdatTq eorNos 1043eDsS 02 MOY +/ 
/x ®ZeY 9 ez038 AnueqstsuoD 10Z ‘qgasoONoO +/ 
/x evrnos Teuthtz0 egy uy seueTdarq # +/ 


tazqufod { 
/x (sTextd) seqeutpr00D y/ !K ‘x GaoM 
} qonzqs zepedxy 
/» “yUnyo qwap & ut pezoys st qzjqutod Ww +/ 
az3qutog 


fzeqstbeyzotop { 

/*pueqxe ubts 3,u0mM py <<, O8 SALAGN © LSAW ¥/ fentq ‘ueexb ‘pex aLxGn 
} qonzqs zepedé3 
/« *(qoee sej7kq ¢) szeqstbeyzotop go Aezze peyoed e st yanyS dW W +/ 
2048 TbeyzoTOD »/ 


‘zepeerdenata { 
‘qqbyepebed ‘qaptmebed caom 
iqoedsyA ‘qoedswx aLxqn 
{zoTopjuezedsuez3 a@aomo 
/* MOU TOF OTSZ oq Asn y/ ‘Tpearesez aLxGa 
/= Tunge3Agdup zo euondup ,/ fuofssezduoo aLAqoa 
/x enoge peastT enbyuyoe; Suyysew e x/ ‘Hutyseu wLxAGA 
/= (48eu Butpntouy you) seuetd zo # «/ /seuetau wLxaa 
/« deajtq sty zoz uozqtsod A ‘x x/ 1K 'R q@aom 
/x stextd ut aybteq ‘q3PTM x/ ‘q ‘a qaoma 
} qonzqs zopedéy 
/* WHIT we seqyrosep eznjonz3s (GHWa) repeey dewatg pertnbey +/ 
zepeoRdens ta 
(T >> (p << (st + ()))) (m) seqAgmoy euTyopH 
TunyezAqduo eutzep# 
euondua eutyep# 
/» senbyuyoe, uotssezduop y/ 


OsseTysu outTsopF 
ZoTopzuezedsuerzlsepysu Sutzep}# 
ASENSEHASU SUTFJOPH 

SUONYsU euTsop# 

/» senbtuyoe, burysen +/ 


YWgil/ay}l 





: Source Code 499 


IFF Specification 


FTpue# 
/x (s)eTnpou uotjeottdde zoz sojord ,/ 
Jesegeszegaaiy AzerqtI yonzyAs uxeqxe 


/»x setnpou Aq peouezesez y/ 


{ 
/~ ezey of Kew sotqetzea of zpoeds-uotzeotiTddy 4/ 
/*= MOU TOF QO Eq Ysnu ¥/ [iL] peazesey ONOTOA 


‘sbeqs» SNOT 


/x SUB8BZTOS O°Z TOF sheq ueezs TeUCTATPPY »/ 
iqsueZz3ON TOOE 


/= yeoTUeb of Auezedsuezy Jou szepiog »/ 

/* SUB2IDS JO TTOTDso4nyY eTQqeug !TTorOseqny TOOG 

/« (eTaeasnfpe-uou) ditto Aetdsta cepta xewW /O@PTA 'TOOE 
/* SWYOON/eueTd-9 Toy GHA OF 3TNEFEp ‘@Ha ‘TOO 

/» 2dk3 dtto Aetdstp ueoszeao fedAadtton m@iom 

/+ sedXky ueezos Teuotytppe fedXa8 SNOT 

/* ®T3TQ weeros /eT3Tas% ALAGA 

/* MOPUTM TOF uot AzuTsep x/ {JOPUTM, MOPUTMMEN QOnITAsS 

/» seouezezerd ASETTED »/ 


e3e3SaL TOOd 

‘dam, Qz0qqseq Qonz45 
fdas, 34roaqsey QonzAs 
iday 3QzroOgmMeTA 3ONnzZAS 
{UTMy MOPUTM QONnIAsS 
iz0s, weexzos jonz45 
/» O° ueEeTDS TOF »/ 


/= SSOUUSPPTY TeGeTITZ JO o7eys 
/» 32z0dQsez 5 ,MOpUTM 

/s yodysez s ,ueezos 

/x Ketdstp pepeot so yrodmeta 
/* Ketdstp pepeot JO MopuTM 
/* Ketdstp pepeolt so uee1z0s 


/+ ATuo seysnzq pepeotT r0F ‘deugtqrq, denqta qonz45 
/x O° deuytqqeb z0y »/ 
‘Tpeazesey LYOHSN 
/* PepeotT szeqsthexz xoToo Jo zequmu ‘szxojToou ZuoHsn 
/* 8934q UT eTGeRTOTOD Fo ezTs feztsqeqo = SONOTN 

/x Sz0TODAeb Aq pe AeosoTTe JOTQEQXTOTODy pxrOTOD 
/+ sdo eaes pue peot Aq ut peTtiIts /Bured ©NoTO 
/» sdo eaes pue peot Aq ut peTTts ‘pyug zepeexdenata 
/* WETI «/ 

/* 

*suxog zeyj0 Bbutszed suexzborzd 

Zoz peoetdez zo peaouexz oq Kew Kou » 

*seTnpow peqetez-WETI eyy Hbutsn surexzborzd , 

Zoz exe setqetzea HutMoTTOS ouL »/ 


foyujeszeg OFuleszeg  WonzAs 


/« HOWHII ddaI «/ FTPuUSH 
/* SOLO8d ON ¥/ FTpPue# 


{(quzy aaxaQ ‘oureuy guxan ‘dzx AITIa ‘wa, dewata qonz3s)deyoquTzaWa pToa 
/* (WAII XOJZ evrNOS D 2ATIM) SO -oQUTAduq ,/ 


i(Tefoeds quomn ‘sTODysep SNOT 

‘yozs aaomn ‘mors qaomn ‘ozs quomn ‘xozs aYyomn 
‘ZS, uweerDS AONnzA4s)dumpueezDs AUT 
/» (qsnzq z0 ueezos qutid) o'dumpueezos ,/ 


+ (oweueTTy» ALAGN 
‘TastTAUNYyo, YUNYD AONTAs ‘TASTTHUNYSs YuNYOD Jonz4s 
‘xoTooquezedsuez3 quom ‘butyseuw Guom 
‘unbreds3tq GYOMN ‘JUNOD GYOMN ‘ETGeAITOCTOD ULdv 
“qubyeyebed quom ‘uzptmebed quom ‘aybteu qaom ‘UIPTM GaoM 
‘ptepow ONOIN ‘dewjtq, dewata yonz34s 

‘WQTTs OFUINATI ZONITAs)uqTTeaes ONOT 


{(eweueTty» FLAG 
‘ZasTTyUNYyS, AUNYD AonzTAs ‘TASTTAUNYO, YuNYD on7r\s 
‘Zs, users oONITAS 

‘WIT OFUINATI JONT3s) oaesueeTOS ONOT 

/= D7 waTTEARS y/ 


J (wqtts OJUINGTI 3ONT3s)uUqTTPeoTUN PToOA 
{(oureusTTZ» ALAGN ‘WqTTx OFUIWATII 3Onz4s)UqTTPeCT ONOT 


{(@ureueTTS* ALAGN ‘WATTx OFUIWAII JONIAs)uqTTAzenb ONOT 


‘(wqTT, OFVIWTI 3ONIAs) YsnzqpeotTun ptToA 
{(oureveTTy* ALAGN ‘WATT* OFJUIWATI 3Onz3s) ysnzqpeocT ONOT 
/x D°WATTPECT x/ 


‘ (DNO'TN ‘DNOTA) Sswrorzqepou pToa 
(4 OFVIWGII QOnzQs) AeTdstpesoTo ptoa 
J(dtton » eTbueqoey qonz3s 
‘oxeuy, eTbueqzoey qonzys‘opasy eTHueqoey yonz4s 


- Devices 


4‘03xQ, eTBbueqoey qonzqas ‘dttop, eTbueqoey Aonzqs 

‘sods, oThueqoey qonz3s ‘ySty LYOHS ‘OPT™ LYOHS) 3TdTTO ptoa 

‘(LHOHS ‘LYOHS ‘LYOHS ‘DNOIN) XOeqTTezepow ONOTMN 

oY UqTT/dzzF, Opnptout# / (DNOTIN ‘LUOHS ‘LUOHS ‘LUOHS‘» OFUINATI 3ONTAs)AeTdstpuedo, moputM 3ONnT3s 

=, / (ONO'IN ‘LUOHS ‘LUOHS ‘LUOHS ‘+ OFJUIWMTI JONAS) userosptuedoy weerDs JonTXs 

H_ddWWHTI SutTsepH /» (WeezDs 0°Z TO E°T suedo) oS‘ ueEeZOS y/ 
H ddWWATI Jopust# 

/* ‘(4 OFUWINATII 3OnzTQ4s)deuytqeezz ptoa 

f(y OFUINATI JONAS) dewyzTqqeb ONOT 

2 (4 OFJUIWATI 320nIAs) ysnzqeqZeTep pToa 

i (~ OFUINATI 3ONT3Qs) ysnzqezeerD ONOT 

/+ (dewatq zo ysnizq butpeot asnf zy pesn) o-deuytqjeb »/ 


/x peqetez o‘aeszed Tereueb ,/ 
} OFUINBII WONTAS 


D*ueezos rox sheqs<-wqTt peppe - 1T6/E0/LO 


suotytutzep oTzstoeds-uotqeottdde - 
uotjeottdde pue setnpou Aq pepeeu sepntout Fo uoTsntTouT - 


@rn_ONzAAS OFUIWEII JO uoTaTuTsZep - 
y' ddewqtt $(~ OFJUIWATI 30OnrQ5s) AeTdstpeery ptoa 
‘(2 OFUINGTI Jonzys)AeTdstp3e6 ONOT 


YUG]!/Ayst 


yaaewiq|!/ajsi 





500 ROM Kernel Reference Manual 


wana na------- ------ MW&L ---------- «/ 


/quoumzyzsursey { 
/x Oweu Queumaqsut »/ ‘[Log]eweu zeyo 
/* PTETZ ,edka, eqQ uo spuedep 4/ ‘zeqep ‘TeIeEp ALAGA 
/+ (eaoge ees) edXQ souezezyez queumaysut +/ fedX3 qLaAga 
/» xequnu zejstbex Queumzysut sty3 3°08 »/ fzeqstheut aLAGN 
} qonzqs yzopedé3 


/= <3eserd ‘Teuueyo> IGIN = <zejep ‘TeQeEp> +/ T IQIW_ISNI eutzepH 

/* zezep ‘TeQep ezouhyt ‘oureu en asn qsnl y/ 0 ®SUeN TSNI ouTsep# 

/*= “PTOTs nedasan 8 ,FUOUMIASUTFESY OYA TOF squeqsuop »/ 

[4-7-7 27-9 ------- eet eo-onnn-n--- ------- TISNI ---------- »/ 


/s "SUOTJBQOUUe 4xeQ s,TOYQNe ous ‘[]uwHo © sutequod yunYS ONNW »/ 
[47---------------- ------------------- a ------------- ---- ONNY x/ 


/* “zoyQne s,ez0Ds SYyQ FO SCUeU SYR ‘[]uwnd & sufequos yuNYo HAY +/ 
«/ 


/*= "eDtR}0U 3qbTzAdod s ,waod OUR ‘[]UWHD & suTeEQuOD yuNYS » (D)n ¥/ 
/*-------- oo nn-------------- eee ennnnn--n--- -- (>) qyStzXdop ---- +/ 


/» ‘Sweu s,ezxoos TeoTsnu eyQ ‘(]UWHD & suTeqQUOD YunYyoO ANWN x/ 


fzepeeyezooss { 
SYDSILIO ALAA 
JaumqToa BLAGN 
‘odure3 qyomn 
} qonzqs zyepedxsR 
[sere errr osr rn wenn ---------- zepReHeEer0DSssS 


/~ eZ0DS eYR UT syoeTZ FO Qunood 
/* LZT ybnozy3 Oo eumtoa yoeqketd 
/» SyQUTU/ejou TeATeNnb syygzT ‘odueq 


Cm, (uN, (a, '1%.) aT_SNW WWaL_dI eutzep# 
(.T, ‘.8. ‘oN, ‘,2,)aT DIN ISNI dI eutzep#H 


es * /* 

(.0, ‘UN, ‘UN, ‘.W.) QT_INN ONNY_dI euTsep# 
(CH, ‘si. ‘sO, /.W.)QT_DIWA HLOV_GI eutzep# 
(,o4 410 443. 11) ,)GT_SaNW 3UStzXhdop_aI euTzepH 
(a, ‘UW, ‘WW. ‘.N,)a0 DIM GWYN GI eutzep} 
syunyo oTzeued se yZFT/dFFT UT peuTFep MON x/ 


MGHS_GI eutzep# 


(8, 4.0, ‘He 8.) QT_aaWA 
SOWS GI eutsepH 


Gs, ‘.0, ‘WW, ‘.8,)aI DW 
un FFT/AFTT. OpaTOUTH 

yTpus# 

unY eT tduoo/dzzt,, epnTouT# 

H UAIIaWOD FOpust# 


H_SOWS eUuTsyep#H 
H SAWS JOpurT# 


PEs mse se ree 


*zeqnduop ebtuy-ezopoumiog eyQ TOF UoTSIEA sSTYUL 
WHO SWOD - 16/So Azexzqt{T*eszedsst YATM OsN TOF PETITPOW 


‘uTeuop OTTqnd eyQ UT ST eTeMQTOS STUL 
“sqry oTuorq0eTq ‘sexey eae yg pue uostazow Aazzec Ag 


98/2T/z “eZ0DsS TROTSAW eTduts roy suoT{TuTseq H*SOWS 


RRR KKK KEK 


ysnwis/Gjyt 


FTpus¥y 


+ (CQHOM‘CAHOM‘x* ALAC‘ xx ALA) MOUYOeAUN Too 
S(ONOT’ sx FLAG’ yx ALAC) MUA! ONOT 

2 (quy/qut’, FLAG) UNYUaNdy ALAC 

‘(aut ‘» GLxa) dumaqjndy FLA 


/x seqkaqqsp ‘seqkgors ‘qseqd ‘eoiznogd ,/ 
+ (@aOM ‘CaOM ‘xx LAG ‘xx ALAC) MoUyeduN Ioo@ uzr6eqxe 
/+ *(z0zz@ OU) ASTwa suznqezr At ‘esTMzeYIO 
“gnu~ suanjex pue sdoqs 4T ‘seqkgqasp ezts zezssnq uoTReUTASep SyQ 
UNZTEAO pTNom unr e FT Jo seqkgors ATWTT §s,e01NOs eYR pesoxe pTNoM AT FI 
* (MOUYDeA OQUT QUEM AZeYQ EZTSMoOZ 
ey ‘'e°T) seqkiq seqkagsp seonpozd 3y Tt3un szequtod uoyAeuTAQsep pue 
eornos ey3 Sutjepdn ‘moz ouo syoedun ‘seTqetTzeA URINIOd OF SUALNIOd weaTto 


/* ®ZTSMOT ‘gseqd ‘eoxrnosd «/ 
2(ONOT ‘x FLAG ‘xx ALAA) MOUAOCA ONOT usz9qxe 
/x “SZTSPSYOeAXeW SES * 
"moz pexoed eyq zoz ybnoue ebzeT st rezygnq uot WeUTIsep SANOSSY + 
“Moz peyoed eyq so seqkq ut ezts eyQ surnjey “szequTod uot ReuTQsep pue » 
eornos ey butyepdn ‘moz euo syoed ‘seTqeTIeA UFZLINIOd O23 SUMLNIOd weato »/ 


( ( L << (LZT+(@ztSMoz)) ) + (@zTSMoZ) ) (eZzTSMoz)eEzTSpexoedXeW SuTFEOpH 
/» *seq4q Fo Moz, & JO eZzTS pexoed eseDd ysTOM SYR seqnduoD oTOeW STL »/ 


<y‘sedka/oexe> epntTout# 


*zeqnduos ebhtuy-eropoumiog ey3 TOF UOTSTEA sSTUL 


‘upeuop oTTqnd eyQ UT ST STeMAFOS STUL 
“sary ofFuozQDeTAT ‘mMeys eaeqs pue uostzroW Axzec Ag 


“satayoed s,oew Aq peqezeued Sutpooue ours 
ey /, TungeqAgqduo, wyytzobte uotssezduoo unz eyQ squeweTdut eTnpou stqL 


KeEK KKK KKK 


98/22/T *zesseaduop-ejeq roy syepedx3 HW" UmIOVd 


H_UIMOWd euTFopH 
H uMovd Fopust# 


yseyoed/ayl 





: Source Code 501 


IFF Specification 


FTpusH 


(=pHES(» ALAG) /(ZepeeHer0Dss)zJoezts ‘YGHS GI ‘33t)AOIna 
\ (apHes ‘337)UdHSINa SUTFOpPH 
/x “A%UNY UGHS © SATFIM OF STYQ TTeS asnc x/ 


| seutqnoy qzoddns 2©372m SONS 


/* “L770 Agyootea Key IGIW © ST eNTeA ,eIePy »/ 
[4------------------------- ------------------ queags ofureukg ---------- »/ 


/s ‘ao ‘qo ‘aqq‘qw’qa’qa’a = pt ybnory3 8 x 
i#o‘#a@/a'wia‘s = ~ ybnozqa T ‘Ceup = 0 entTea ,e3ep, x/ 
[ron nnn nnn o eo-------------- queags Stshey ----- scone x/ 


(q{seNCeUT. 9 (eUrTLS (TuOMa) ) ) (ewpLs) 5tsqeuy, eutsopH 

(QsTUSNeWT A << (AseNNeUTZ 3 (CUTTLS(HOMn))))  (eutLS) StsNewTL suTsep} 
{= 2880008 PTET »/ 

/* PTSTZ HStsqewsy roxy yseu aTq «/ LOXO =ASENCEUTZ SUTFOpH 


€ IFSTUSNEUT oUTJopH 


/« PTT StsNeuty roy Qunod asus »/ 
84X0 ASENNSUTQ euUTyepH 


/« PT@eTF Stsnewyy xox yseu tq »/ 


‘itseuris { 

/+ 930U YISZT = L 

-** ‘eqou zeqzenb = Zz ‘e jou 

3TeEY = T ‘eQ,0u ETOYM = O :Stsqeoutie«Z 

St ,TOAeUTUOUEp,, ernQeUhts SUT 

/+ T + STsNewyy ,,z0R3ezeumU, ornQeUbTs suUTQ 
/x 5tgeutL GIs = ‘8: 


te: Stsqeury 
‘g: BTSNemy3 
edXq peubtsun 
} qonzqs zepeds3 
[errno nn nnn nnn nn nn ee queags 5tseutL 


(aztusaejou << (yxseNCeZOT 3 (S30Us(MYOMN)))) (e30Us8)UOTSTATC eUTFOPH 
(joqdej0u 3 (eB QOuSs (TYOMN) )) (eQ0us) JoGsI eUTsepH 

(QF FUSNeEQOU << (XseNNeEQOU 3 (@ROuUs(TYOMN)))) (e30Us) QeTdNIN SUTFEPH 
(Qnoetzej0u ¥ (eQOUs (CTYOMN) )) (eQ0uUs) peTLsI euTFEpH 

(proyoe jou 3 (eQous(qYOMN))) (e308) PrOYosSI SUTzZepH 

/= :880D08 PTET, x/ 


/x yop ‘3eTdn~U ‘uoTsTATpP » 

SPTOTF woyAernp [Te FoF yseu 3Tq 4EXO ASEWINGe JOU eUTJepH 
8zZTadejou AseEWdejOU eUTsOpH 

(a3 F4Usaejou>>z) 8ZTaejOuU eUTJepH 
(az FYIsdeqou>>9) pode jou eutzop}# 
(ag Fusdejou>>¢) ZEGejOU eUTFOpPH 
(az tysdejou>>y) 9TqGe jou eUTFep}H 
(as TFYsdejou>>¢E) gqejou eutjyop# 
(azTysdejou>>z) paezou eutTyep# 
(as tysae jou>>T) zZqejou eUTTePH 
(as tysdejou>>0) Taejou eutzepH 
0 3zF}USdejoU eUTJepH 


/* PTOTF UOTSTATP eYQ Toyz Yseu 3Tq x/ 
/« WOFSTATP 9R0U BZT/T 
/= UOFSTATP SR0u YRINOSZ-AQxTs 
/* YOTSTATP S30uU YRpUCDeSs—AQITYR 
/* UVOTSTATp SR0u YRUSSAXTES 
/+ UOTSTATP ej0u yQYySTe 
/x WOTSETATp SQjou z9eRATeNb 
/*« UWOFSTATP eQoOu FTeY 
/* UWOTSTATp ejou eTOUM 
/x PTSTF woTstatp oF Aunoo yaztys 


YSNus/G}y! 


/* PE3I0p St Sj0u (€>>T) jodej0u SuTsepF 


/* PTOTS JoTdn~u eyy roxy yYseu 4Tq LN©JOU YASEWNEQOU SuTFopH 
/x yTdnAdes e st ejou (QF FUISNEQOU>>E) LN© ZOU eUTZFEpH 

/* 3eTdnquTnb e st ejou (QZ TYSNeQOU>>z) GNeQou euTyop# 

/x WTdtrAZ & st eQoT (AF TYSNSQOU>>T) ENSQOU SUTFEpH 

/x PTOTZ JoTdn~u roxy Qunod yzTYS ¥ AFTISNEQOU CUTFOpH 
/* PXIOYD/ezOU AXeU OF PETI ST PIOYo/e jou »/ (9>>T) 3noeTLe_ou euTyop# 
/x 930U 4xeU 02 pepzOYS st SejouU ,y/ (L>>T) pxroyoe jou sutyep# 

/» “9a0ge ‘spTeTy pexoed-qtq egg ueYQ TeyReT suoTaTuTyZep HuyMoT Tos » 

aya Bbuten Surastys pue ‘Sutao ‘bupyseu Aq epod 30efqo xze330eq Ae5 Aew nox x/ 


/* 

"PIOM 3TG-9T & OFUT QF syoed zSeTTduOD eYQ QeYR * 

ufeqzes eze nod ssetun edkq styR FO esN TenQoe ey PToae os “QUT ue UeYR » 
zeTTeus ButyqqAue ojut spretsy 37q yoed Jou [Tt sxreTtduos OD eulos y 
-Katque atq-9T e& eq o3 pesoddns st ejons uw :butuzem »/ 


FeQ0ns { 
/*= ®30U U38ZT = L “°° ‘eR0T » 
zeqzenb = Z ‘ejou sTeYy = T ‘eR90U STOUM = CO x 
TUOFETATP-xxZ ST UOTQeINp ejou oOTseq fg: wotstatp 
/« @/¢€ Aq vuotqerap ATdyzatnu /ejou pejjop "kT: 0p 
/* ytTdnades = ¢€ 
‘getdnqutnb = z ‘eTdTz3 = T ‘eouou 0 ‘Zz: «6eTdnzu 
/* PIOYD TO ejou yxeu EY OF PETZ = T ‘T:  -qnoeTt2 
/x 230U pepzoOYS e Tt ‘T: pzoyo 
/x« 480X = B8ZT ‘LZT O23 O ZeEquMU eT0R IGIN ‘g: 9uog peubftsun 
} qonzqs zepedAy 
---- 3S59Y TO SVONQISET “OQONASITA WUeATS ---------- »/ 


xTeW AIS euTzep# 
/x “UOTASZTprepueys y 
emngnzy ToZ peazesex :ygz ySnozyqy dn sontea ais Bbututeuer euL »/ 


/+ ‘Wa Uy yzreuU-pue ue rzoxZ peazesezr CIS +/ ssz 


/= °8QUeATS OTsnW QUeAsUT TOF peazeser :6GT YSnozyQ PyT senTea CIS x/ 
/*s"eqnutw zed sjeeq ut ebueyo odueq euttur 9ET odueL dIs eutszop# 
/»x “xouez=¢ ‘O3TW=z% ‘sseq=T ‘SeTqezL=0 

‘ebuey> JeTO euy{ut Set 


_3°TO_GIS eutyzopH 
/* (szeouenbes) zequmu jesezd IdIW 3658 PET sera _IGIN_ GIS euTzopH 
/x (szeouenbes) zequmu Teuueyo IdIW 368 €€T  TUYD IGIW_GIS eutzep}# 


/« “YORIA stqA FoF sumyoa yes Zet oyureudq_ais eutyop¥E 
/* “42k sSTYQ Tox emnqeubts Aex jes TET StsXey_dIs eutsepH 

/= "APeTQ sSTYR TOF ernQeubts ouyq Aes O€T HtseutL adIs eutzop# 

/x “YORIA styA TOF Tequmu jueumzysut jes 6ZT  ueumzyjsur dIs eutzepH# 
/» °930U & se Aeutoz eQep cures ‘Qsez & 8cTt qseu dIs outsop# 
/x * (qo3td) zequmu eu0Z IGIW eu sT_dIs 
eyL “seqjou eze (9 = 3atq ubts) e7ONQseT CIS - 
ybnozry3 SAONRSITA GIS ebuexr eyQ ut saIs L2t SIONQSET_CIS outTzyopH 

0 SIONASITA GIS Sutzep# 

/x “vGIS, sepoo edX3 Queags »/ 


iqueags { 
feqep anzqa 
*qI8 @LAGO 
} qonzqs zepedxy 
/x« "3Ue4e8 TeoTsnu eTduts :jueagsS »/ 


/+ &3ep quepuedep-qis «/ 
/x poo edAQ Queags x/ 


/+ “[]3ueags ue sutequoo yunYo MWwaL +/ 


ySnWs/aj}! 





vices 


De 


502 ROM Kernel Reference Manual 


‘aSTW¥d = eaesog 
‘(t)abze = ene 
(z==062e) st 


Pas { 
!(90 NaoDT' 1) oAq 
! (ebesn ‘qq6przhdoo ‘,,u\seu\sy,,) sQUTId 
} 
((,2,==(0] [T->bze)] abze) 33(T < o62e)) zt 


‘gouL : asSTwa 2 o6ze = qmmorg 


fu ‘s ‘d ‘x qut 
‘goal = eaesog ‘Too 
tdd3,y aLxao 
feztstTd ©ONOTO 
‘ezqxe ‘epoud ‘qqSteqd ‘qaptad ‘yjdep ‘aqSteq ‘yaptTa Taonsa 
7790 = zxozz0e SNOT 
fuqs, ‘Uqx, ‘TION = wqy dewata 3onz48 
‘{0} = Aummp dewata qonz38 
TION = dz, qz20a3sey Qonz348 
} 
(Abzeyy TeYD ‘’oHze Quy) utew ptoa 
/* 
NIWA « 
»/ 


ZqxeQpue, ALAGA 
T3xeqpue, FLAGA 


‘.°ayxe 09 Aey zo uoAQnqesnou ssexd, 
/,°outQ e& qe p ‘seuetd pz poketdsta,, 


2 hG 9G Sn PE ER 78 TE nO 
Ln n9Dn nGDu /nPDn nEDw nZDu nTOe “n0Dn 

1 bM en  n9Gn SS Pn nbMa nn ZIn oT n0Un =] soureuqSzy FILAGA 

! WATT ItAPZT AWA, = SMeUUGTTs ALAA 


TOOZO ‘TOOZO ‘OTOXO ‘OTOXO ‘oOTXO ‘ooTxo } = []szsF0> TuOHSA 
800X0 ‘000x0 ‘080x0 ‘000x0 ‘o08zo0 ‘o00x0 } =[]s37e38>5 LaOHSA 
‘[ze]etqejzoToo TYoOHsA 


v SENWIduDS euTsTepH 


‘(z]wqtt* OFUIWMII JoNnIRs 
/» 8eueTZ WHIT PSEAEOOTTE zn TO" »/ 


{lyzsyou aLxgo 


faU\FFF OOTTS 3,7Bd, 
(]wewou gLxAGO 


/,u\Azoueu ybnoue 30N,, 


*{ 
_  SNOd OVE 
‘xqgod GI ‘WHII GI 
} = []sdoqsuqtt SNOT 
/x to doqs 03 yUNYD WATI +/ 


‘ 
*{ 
_  3NOd SYL 
‘ONaD GI ‘WHT GI 

} = []sq0eTToowqTt SNOT 

/ pezeyzeb 9q 0% (ETTZ UT EMO UeYR ETOU) sYUNYD WOTAOSTTOO WHII x/ 


Hf 
aNod SVL 


*qubtzAdop_aq ‘WA'II_dI 
‘HLOW GI ‘WAHTI aI 


oowsqiqrz/owsequqre/sade 


z abe 


‘ZuoD_dI ‘WaTI_aI 

‘OWWO_GI ‘Wa TI_dI 

‘aqwwo_dI ‘wWalI_dI 

‘GHWa GI ‘WATII aI 
} = []sdozduq tt pees 
* 
(epod ejezedes qATM Ano 76e9QTIM Oq TITM AeqQ) Ano yor STTF OqQ » 
©37IM eM ueYyM weyR dtTys UBD OM Of AsITZ ONY PUES YW ‘CHWE ISTT x 
peqqerb eq 03 syunyo Aqredozq WHTI x/ 


‘qMmox, a ‘IOod 


“ 
/« moputm zo edky, NaTAOSNOLSND 
/= YUSTOHZeH PUe YIPTMXEW ‘o ‘0 
/«= 3QSTOHUTH PUS TIPTMUTW 
/» zequtod dewata 
/s peuedo TTT} TInu 14d ueezDs 
/« Suyzz3s eTITL 
/» szequtod efeur pue qebpes «/ Ss ‘TION 
‘ WALA | SLVALLOW | HSTUATARIWOON| HSTAAMY LIWWs | ssaTagaiog | doumiowa 
/* soteq sheta wats sbeta aNOdI »/ ‘SNOLLNGISNOW | ATIWTTINVA 
/x UWeayooTa pue uedTTeqeq «/ ‘T- 
/= VUSTOEH PUS TIPTM x/ 
/x ebpadoy pue ebpaazet x/ 


} = auku MOPUTMMON 


J»  yxodmeta 03 29d OZ x/ ida, qrogmety qonz4s 
/» 3x0a38eY 09 79d TOF 4/ idimy 4zoaqsey = onz3s 
/= @INQONIAS MOpUTM 03 TAd TOF y/ SUTMy MOpUTM 3>0nNIT35 
/s exznQoNIAS ueexos 03 329d TOF x/ {208% ueer0s qonz46 
/x« ®INAONIAS CFUIWATI SYR UT STQETTeAS osTe ore spTEeTZ es9yQ - SION x/ 


‘TION esegosriedidiIx AzezqTt qonags 
‘TION esegxy5, AzexqyT 3onz38 
‘TION esequotqynqur, AzxexrqypT qonz3s 


‘,,(ueatS eueupeoT ou Jt speot/seses) [eweupeot] oweqaztqrz :ebesn, = ebesn,y eyo 
‘, (oTaeanqtzastpew Ateera) ¢g* Lea oweqataqyz. = aybtszXkdopy zeYyo 

JnG°LE CUPaITGPZ -UgASO\. = STEAy TeYD 

T SOUWNIW SuTsepH 


/(z0zze jut‘s, aLxGn) eAq ptoa 
/(pfoa)dnuee{T> ptoa 


sTpuc# 

/« Aytveex x/ { /(0)uanqez } (ptoa) zzroqeyYYoO ut 

/= Guy Tpuey O/THLD eot39e1 eTqestd «/ { /(0)UINZeT } (PFOA) MIGXD WUT 
AOILIVI FOPrt# 


uy ddeuqit/dgzt, epntout# 
/ 
STTFOXEN Ses 
seTNpou gzI Tezeaes yatm ebexutT sezynbez 
‘out © 3e seuetd » sXetdstp qenf{ (eweuetTts e ueatb xt) AtTTeuotado 
outa e ye seuetd » noX 03 3 smoys pue Ysnzq e se AT speoT ueyQ 
‘WHII 3T9-~pzZ © SE AT senes ‘xeQsSeI ATq-PZ EB seqeeTD YyOTYM eTduexg 


WHO zeuddeyos “5 T6/SO > OouredzTqEZ 


| eed sowsquqrc/owequqre/sade 





: Source Code 503 


IFF Specification 


!((qzoaqsey 3onz4s)zoezts ‘dz)weweezz (dz)3T 
TION = deur tqzq<-[o] watt 
2((Z >> ezqxe) + (dewata qonz3s)zoezts ‘dewytqzq<- [0] uqTT) weyeergy 


{ 
£(qq6yeyq ‘yQpta’ [x] seueta<-dewytqzq<- [0] wqTt) zeqseyeerg 
([4] soueTa<-deurjtqzg<- [0] watt) st 
} 
(+44 /q3dep>x /o=%) t0z 
/» deayztq xno eerZ »/ 


{ 
 (eweuuqTt 
/s SASTTAIAGS »/ ‘TION ‘TION 
/x quezedsuezy ‘Butyseu ,/ ‘9 ‘ouonysu 
/x STQeRIOTOD x/ ‘o ‘oO ‘T'TAN 
‘qqbyeqd ‘qaptad ‘3yfteq = ‘q3pTs 
‘epoud ‘dewjtqzq<-[o]waTt ‘[o]watt)uqrteaes = zorze 
/ (eueduq Tt ’..a\s¢% Sutaes,,) Quad 
/*« WHII 379-72 OF Eves x/ 


{ddq = [0] seueta<-uq 
‘qadep = q 7deq<-uq 
{ 
'(z ‘[x4)seweuq6z ‘dz) 3x0, 
/* 3x03 eueuqtq q6z zepuez ,/ (8 + (8 « 4) ‘OT » 4‘dz)eaoH 
i [x] seueta<-aq = [0] eee 
/» euyZ eB Ze [T sxqdeuetd ut dems ,/ (+44 /qQdep>x /o=%) z0F 
!T = q3dea<-uq 
‘(9] seueta<-wq = ddq 
/* 
yjdep pue szejutod ey q3TM ETPPTS wed em os 
qzodmeta zo uweezos e zo axed jou st dewatq ano » 
*seuetd eqq ut etTqeztubooez Buty jeuos 3nd »/ 
} 
(zx0220j;) 3T 


{ 


/* ze qutod ysiztz pue x/ 
/x YWdep ezojsez ,/ 


/» zequtod euetd asatz enaes y/ 


{ 

: (Dawe ‘dz) przajes 

/ (1 dz) weawjes 

‘Toxo = xs8eWK<-dz 

fuq = dewata<-dz 

+ (dz) eee 
= este 

. ‘WEWON WUAAII = oOzzIe 
((QQWaTD GWEN’ (Q20gR8ee QONTAS) JOeZTs) WEROOTTY = Sees 


(r0220 5) 3F 


{ 


/» SUTQ & Qe OUeTd T AEpueT TT,OM x/ 


{ 
‘(o‘ (aqSteq‘qapta) azisswa ‘ [4] seueTa<-wq) zeeTOITa 
} 
= (zozze j,)ZFT 
‘WAWON WUAAAI = Tore 
(((aqbyeq/qapta) zeqseyooTtTyY = [4] seuetTa<-aq) j A 
(+44 /(z0zz0;) 39 qAdep>y /o=zr0rTE ‘o=x%) TOF 
! (aubteq ‘q3apta ‘qadep ‘uq) dewatagtar 
idewytqzq<-[o]wqtt = > 
(Cawato aWan 


‘(z>>ezqxe) + (dewata 3onz4s)zoezys)weypoTty = deuwytqzq<-[o]wqTt) st 
fo : 8 - yadep ¢ g < qadep = exzqxe 


py abe aowsqiqrc/owsquqre/saae 


/* 
seuetd pue deuwqtgd e3e°°CTIW + 


+/ 


feaesou oj06 (eaegod)) FF 
‘ (qubyeq‘yapta) azisswa = eztstd 


‘To > SOWI é 00p =< aybteyd =| spond 
‘To|: SH4IH é oF9 =< YapTMd = espoud 
‘aubrey : 002 é 002 > aubtey = aubteyd 
‘yapts : oZE é OZE > UIPTA = Yaptad 
/« WAII peaes rox epou pue ‘qyhtey ‘yaptTa obed »«/ 


‘vz q3dep 
‘ooz = aubteq 
‘oze yapta 


/* WATI 3FQ-yz owep zno Huyaes TOF ¥/ 


! (TIwa_Ndngama ‘YFFTOU) OAq ((()FATOOTTY = FFT OFUTESTea<-[T]wWqTT) ji) FT 
{(1Iwa Nanas ‘ysstou) eAq ((()aaIOOTIW = FFT‘ OFUTESIea<- [0] WQTT) i) FT 
/* 
ewezz OZ seTpUeYy FIT COTTW + 
»/ 


‘Colwatts = (T]watts 
iauduy = soputa<- [0] WqTT 


isdoqsuqTt syyodojs ‘osuresred<- [o]uqtt 
FS{QOOTTOOUqTT S{AYOIOET TOO ‘ osuloeszea<- [9] wqTT 
isdozduqtt syxyodord: og ureszea<- (Oo) uqTTt 


/* 
(CHNH SXTT peztnbez euos) ut peysezequT ere eM 
syuNYS uoTQoeTToD pue Azedord eyy peutyzep eaey om eACqY 
-uofqeottdde 
ZNO x0F spTETF OFUIWNETI tno dn jes om ore 


= 2 ‘(TIWa NaoLT ‘weuow) ofq 
((CGWaTD GWIN|OITand AWaW‘ (OFUINATI 3OnzT48) JoezTS) WE_OOTTY 
(« OFUIWMTI Q0nzQe) = [T]waTT)i) FF 
_ 2 ‘(TIwa NOLTa ‘weuow) okq 
((CQWaTD GWEN|OTTand aWaW’ (OFUIWATI 3ONIYQS) JoOeZysS) WEAOOTTY 
(« OFJUIWETI QOnzQs) = [oO] WqTT) i) FF ; 
* 
S3OnTAs OFUINETI COTIW x 
/ 


i (Naum NdoLma’,.u\AzezqtT eszedzzy uedo 4,ueD,,) Aq 
(((o/,AzezqtT*eszedzzty,,) Azezqtquedo = esegeszeagaI) i) FT 


‘(NUM NOTA ’,u\*Azezqt¢y sotydez6 uedo 3,ue9,,) eAq 
(((o/.Azezqyt’ soyydezb,,) Azexqyquedo = esegxzd) i) st 


/ (AWM NUOLTY’,.a\‘Azerzqy¢T uotyynquy uedo 3,ueD,,) oq 
(((o ‘,AxezqyT uotgznquy,) Azezqyquedo = esequot3tnqul) j)FF 


/» seTzezqTT uedo x/ 
{ 


a owsqiqrz/oweqiuqrc/sade 





vices 


De 


504 ROM Kernel Reference Manual 


‘yajdeq<-uq = yQdep 
/x deuytq euetd-p~z eq x/ ‘dewaytqaq<-[T]waqTt = wq 
{ /» Gdeuytq s,ueezDs ,/ ‘dewata<-zos3 = uqs 
/ (r0ozze) 4txe /+ deuytq ezeds x/ ‘Xoump3z = wqx 
£()dnueeto 
£(8/,a\s¢,)F3aFazd ( (qumozgj) 39 (Sx)) FT ? (x98<- [9] wqTT) quozrgoLueezDs 


(zozze jut’s, gaLxaa)ekq pytoa 


{ (a0 NanLza) 3txe 
/()dnueeto 


! ( (zozze) zzegat ‘,U\s%,,) FRUIT 


£(,t\euog,,) 3utazd 
! (Lo] watt) AeTdstpesoto 


{ 
/x PEpecet FT STFFTFESOTO ‘STOTOOD soOTTeep »/ /({t] watt) qenzqpeotuan 
i (atabts du<-7rogrtesn<-UTM>>T) ITEM 


‘((zqxeqpue)ueTzqs ‘zqxeqjpue ‘dim) qxeL 
(ozt ‘pz ‘dam) esonw 

/((Taxeqpue) ueTz3s ‘TQxeqQpue ‘dzm) qxeL 
(08 ‘yz ‘dzm) eaoy 

I(T ’dza) weayaes 


(9 ’3x0gQsey<-7083) seUQeS 


{ 
‘ (og) AeTed 
i(9T ‘eTqeqzoTOD sen yecerres 
‘{sanwiauos / d ]szyop =+ q6z (1 3 ae 
* 
unB zed sqtq g eaey ATUO OM y 
eouts seuetd z Azeae z0z unbh dumq ;/ 
‘q6z = [u]etqeqzotoo este 
daaxQ = [ut] etTqeyzoToo wey 
(+4u ‘oT > u /[sanwiayos/ d]sqxeqso=q6z ‘o=u) z0z 
/* 
eotKq entTea qb6z yore Bbutsn Aq x 
szojToo und zed 3TqQ-p YATM XOTOD yATqQ-g eQeTHUy »/ 


? (TIAN ‘40%0 ‘0DX0 
‘qybyeH<-z0s ‘YAPTM<-20s 
‘0 ‘0 ‘uqs 
‘o ‘o ‘wqx) dewatasta 
/» woros ey3 OF soueTd Atta +/ 
{ 
[s] seueTq<-uqxz este 
[s]seueta<-uqx (q3dep > (s+d))3T 
} 
(++8 ‘SaNwiauos>s ‘o=8) z0z 
$(0 ’3x0q38eY<-2089) JseYIES 
} 
/s CUTZ © 3e Y ¥/ (SANWIaNOS=t+d ‘yqdep>d ‘/o=d) z0z 
/« seuetd pz eyg mous +/ 


{--q3deq<-ugqx ‘TION = 
‘[s+d] seueta<-uq = 


! (qubteu<-z08 ‘qQpTM<-70s ‘SaNWIauos ‘wqx) dewataatuLl 


9 a6ed oowisequqrc/oweqiqre/sade 


(x0zz9) FF 


{ 


{ 


{ 


} 


?(Loluqtt) eT tsyTesoTo 

/* 

PSITF SSOTO TITM em os ‘OTT eyy worzzy syuNYoO ~ 
Kue Kdod zo euturexe 03 peeu 3,U0p OM - SION +/ 


/((,U\TngsseDons YsnzqpeoT :ouweq3taqpz,,) Snq)q 
} 
(((eweamgqrt ‘[T]wqTt)ysnzqpeoT = torze) j) FF 


ida<-[o] wqtt 
idzm<-[o]wqtt 
tupa<- [0] wqTt Ut 
/zos<- [0] WqTTt aos 


! ((SanwiIauos ‘.U\rngssesons (seuetd pts) Aetdstpuedo :oweqatqyz,) bnq)a 
} 
este 
{ 
i(,u\Setdstp uedo 03 peTTea,) squtad 
} 
( ( (Sureo<- [o] wqtt 
‘(SaNWIados ‘seuetau’ pywg<- [0] UqTT) NIN 
*(q°pywa<-[o]wqtt ‘aqbteopebed: pyum<- [0] watt) xn 
‘(a pyug<-(o]uqrt ‘qaptmebed: pywa<-[o]wqtt) XW 
‘Lo]uqtt) Aetdstpuedo) j) s+ 


/* 
"SPleTZ esoyy 
SZTTIETITUT TIT yotym ()Aetdstpuedo osn TTTM em ezey *AeTdstp 
ano zoz da<-[o]uqty pue ‘dzs<-[o]uqrty ‘dza<-[o]wqtt ‘utm<-[o]wqTT 
‘zos<-[o]wqTt ezFTeTATUT ysnu nok ‘os Zt 4nq ‘AeTdstp 

anoX uedo 03 seutqnoz umo anoX esn prtnoo nok - e30N x/ 


!((Sureo<-[o]uqty ‘seuetau*pywa<-[fo]uqtt ‘uy pywa<-[o]uqtt ‘m*pywa<-[o]wqTt 
‘ ,U\ZTS$=PTopowm’pTs X PTS X PTS ST WATI stuy ‘Azenb zeqze sagt nay en) Pens 
(( (eweuwqtt ‘[o]wqrt)uqrtAzenb = zozrze) j) st 


{ (eureuuqT t 
+,,u\owfFQ e Qe seuetd p AetTdstp pue deurjyq e se sz peoT oj butqduez3v,,) sz quypad 


‘ueezos eueTd-p ano ut ewty e& We souetd 7 3t 


buyketdstp pue (deujtq) ysnzq © se WATI 374-pz eu SutpeotT ueyq - 
Ketdstp umo ano BSutuedo ueyq - 


(pegnduio> zo Teez) SNYO PUe GHW SIF 365 03 WETI Ue Huzpkzenb 4saTtz - 
5utqezr3suouwep eze em ereR 


+ (deurytq) ysniq © se At PEOT TITM eM Os 
WETI 3T4-pz © St STYR ‘TeEACMOH “QT UT WaTI ue AeTdstp pue 
ueezoe eqetidoizdde ue uedo oj ()uqTTMoys esn prtnom nok ATTeUION 


:eAesou 


_ { 

‘(Trwa NgaLTa ‘yn 1) eAq 

/ ( (rozz0©) zzeg aT‘, U\ ss) FIV Ad 
} 


(x02z9e) FF 


{ 
g abe os owsequqrc/owsquqre/sade 





: Source Code 505 


IFF Specification 


O3TIM 8M USEYM weyR dTXs ued OM OS ASITF ONWOD PUe dWWO ‘CHW 3STT x 
peqqez6 oq o9 syunyo Aqzedozq WATI x/ 


seuog ‘qmuioza 'IOoe 


7{ 
/* oputa Jo edxy NZRIOSWOLSND 
/= VHTOHXeW PUe YIPTMXEW ‘o ‘0 
/« VUHTOHUTW PUES YIPTMUTW ‘oz ‘0S 
/* ze qutod deyata “TION 
/» peuedo TTT} TInu 24d ueezos “TION 
/» Sutras eTATL “TION 
/» szequtod ebeuy pue yehpeo »«/ _ ‘TION ‘TION 
‘ WALA | FLVAILOW | HSAMATATAWOON | HSTAITA LUUNs | ssaTaaaog | doumiova 
/* moTeq sbeta yqtm sheTa aWOdI »/ ‘SNOLLNGISNOW | ATMWTTINYA 
/+ WeaxYOoTE pue usdTteyed x/ ‘To {To 
/« 3A670H pue TaPTM »/ 


/x ebpgqdoz pue ebpgazeT x/ 
} = mudu MOPUTMMON 


‘Bsu, ebesseytnqur  4onz4s 


/« 2z0dmeta 09 roy »/ day ATO_MOTA qonz3s 
Js  WoayseyY OF Z0F +/ idimy, qrodyseu qonazys 
/~= @ZNAONTAS MOPUTM OF xoF x/ JUTMy MOPUTM 300235 
/* 2z0AONAAS wSeeTDS OF x0F x/ 1208» ueez0s qonz3s 
/» ®2nAONIAS OFUIWNATI UT SETQETFEAR OsTe ere spTEeTS Sseyy - SION x/ 


‘TION esegqesizegiary Azexrqty Aonz3s 
TION esegxsox AzexrqyT onz35 
‘TION esequoTazTnqurly AzerqyT 3onz35 


foureueaes, TeYo 


/,u\pzeoqdtTS xox ("DQ9e ‘ZO- ‘TO- ‘D- "et) [FFuNn]o- oureueTTF esn. 

nU\Qsep 02 seaes ‘Ysnzq SATTq pue speotT ATTeuotyado ‘eoaznos sXeTdsta, 

wt\ (ueezDs qutad 03 d-niLo) [eureuysnzq] wqTT3sep wqTTeornos oweqwaTr :ebesn,, 
= ebesn, reyo 

/, (oTqeanqtzystpey ATeeza) ¢°LeA owedWATI, = 3StrAdop, eyo 

/uG°L€ OWEGWETI :WAA$O\. = sTeAy TeYO 

€ SDUVNIN eUTzFOpH 


SJONWHOFAYS SutTsep# 


/(zozze 3uy‘sy aLxGn)eXq ptoa 
‘(pyoa)dnueeTo ptoa 
‘ (pyoa) Ssuryo ptoa : 


FTpus# / (eseqeszeagar) AzezqQyTSs0TO (esegqeszeaggaI) 3Tt 

/= Ayqjeez «/ { /(o)urnqez } (ptoa) ytoqeyYyo jut / (esequotqpnqur) ArezqyTSesoTO (@sequoTtatTnaul) st 

/» SuyrTpuey O/TALD eofaqeT etqesta «/ { ‘(0)urn3ez } (PTOA) mMIaxD QUT / (esegxzp) ArerqTTesoTo (esegxs5) St 
FOILLWI Foprt# ‘ 


‘((OFUIWATI ZONTAS) JoozTts ‘ [T] wqaTt) weyeorts 

wy ddeuqtt/dgst,, eapntout# i (FFF OFUTSsred<- [(T] waTt) JdI9eTA (FFT OFuTOsreg<- [T]wWqTT) FF 
} 

/* ({T]wWqTT) Ft 
SETTFOXeN Ces - seTNpow dzzTt Tetences yRTM ehexutT sexztnber » { 
/ ((OFUINATI 2ONTAs) FoozTs ‘ [oO] wq TT) weyfeetT 


* 
“pzeoqdt[TS 03 eaes XO WOTF peer Of SUeUeTTZ se (DQe ‘7ZD- ‘TD- 10) D- eBH * /(gzFT  OFuLeszeg<-[(O]wqTtT) ITSEeTT GEE Eager 


(d-Tazo) ueezos e Buyqutazad AttTeuotydo pue ‘waTr ue Gutaes 
‘asnizq e bButpeot ‘waTr ue butAkertdstp sejerqsuoueg ea. 


()dnueeT> ptoa 


* 
Wa zeuddeyos “9 T6/SO > OWeqWaTI +/ 


| e6eq Dd OWSQINGTI/OWSGING TI/sade L ab6ed dowsguqrc/owsquqrc/sade 





vices 


De 


506 ROM Kernel Reference Manual. 








/ 
“3y wWory sTEYAO SYR SOTO pue euUerz QTNeJep euUO 
SZTIETATUT TT,/OM ‘S,WHII TOF ore seuezy ANO Jo TTe eoUTS 
(CHA ATT pezytnbexz ewos) uy peAsezequUyT ere om 

syunyqo uotqoeTToo pue Azedoizd ey3 peutzep eaey om encgy 
*geuezy s ,uoTqeottdde 

ZnNo XOF spleyts OFUIWATII 3TnNezeop dn Aes om or0_ 


Kee KK KKK 


* 
~ 





{ 
[ads] suqTtt 
aan 


este 


+ [oj suqtt 
+ [o] swqtt 


a 
s 


= _ ! (TIwa NoLTa ‘weuou) eXq 
((CawaIo SWaWI|DITANd ANEW’ (OFJUIWATI 3ONTQS)FOOZTS » LNNODIN) WOHPOCTTY 
(x OFUIWATI QOnzTQs) = [0] swqTT) i) FT 
/* 
(qysnzq ‘ueezDs ‘syTneyJep TOF yore uO) sAONTAS OCFUIWATI SOY OCOTTW x 
+/ 





‘ (seivm NuoLea’,.a\‘AzexqyT eszedzzq uedo 3,ueD,,) ehq 
(((o/, Azezqt{ eszedzzt,,)Azexqyquedg = esegoszedgal) i) FF 


 (NMWM Naniaa’,,t\*AzezqtT sotydexb uedo 3,ueD,,) oAq 
(((o/, Azezqtt* sotydes6,,) Azezqyquedo = esegxyd) i) FT 


‘(NaWM NeoLaY’..u\"Azezq¢T uopanguy uedo 3,ueD,,) eAq 
(((o ’,AzezqeT-uozapnquyz,,) Azezqyquedo = esequot3tnqul) i) FFT 


/* setzezqTT wedo x/ 
{ 






= { 
‘(mo Naotaa’.u\"Supatzg,)ehq  (,u, == sue)zt 
fozxo | 9 = sue (suej)st (,U\, =i (()zeqOQ06 = 5))eTTUM 
‘o = sue 
/ (eueueaes 
‘y & (@ zo A) egyamreag “s3stxe Apeorte 4\s%.\ OTTF 32d.) FIUTId 
+ (SOT) yOoTUA 
= } 
((awaa Ssaoow ‘eureueaes) YOOT = oan 
((,.2-,, ‘oweueaes) dupz3s) FF 
/x sqstxe Apeexzte eTtzZ Asep Fy uxreM ‘pxreoqdyTO Jou ysep FT x«/ 


{ 





fyeezq 

/([t)a6ze = oureuuqtTt 

i(zjaize = oueueaes 
t¢ eseD 

‘(ejabze = oueuygsniq 
ty essed 


} 
(262k) youtTas 


= { 
(m0 NUOLM’...) Aq 
2 (ebesn ‘AybyzAdoo‘,,u\seu\sy,) FIUTIAd 
} 

((,é.==(0] [T-obze] abze) | | (SoUVNIN>>bze) ) TT 





‘gouL : aSTwa é obre = quuozg 


oD OWSGWE 1l/OWSqNg TI/sace 


z o6eY 


iZ0ZIZ® SNOT 
SAOOT AULA 
io ‘sue ‘TIAN=eureuysniq, ‘TION=eueuuqTt, FLxAGA 
sTpus}# 
{ZOIZEAES ONOT 
‘Bored, yunyobue 
fyunygo, yUNYD Aonz4As 
SZONWHOGAYS at 
(abxzeyy zeyo ‘obze Qut)utTew ptoa 
/* 
NIWA + 
«/ 


= [ZNNOOIN] suqTt, OFUINATII 3ONTAS 
/* SeweTZ WATII No z0g x/ 


€ ZNQOOIN eutyzeopH 

z aos eutszep# 

T oud SUTFEpF 

° qaqa rege 

* 

ueeyos pue ‘ysnud ‘3TNegad x 

sewery INO SDUeTEeJET OR seExEpUT ANOS ,x/ 


{lugztou aLzqa 
{]wewou aLzGa 


JyU\FFTF COTTE 3,08), 
/,,u\Azoweu qhnoue 3oN,, 


‘ 
Hf 
i ‘{uLZ “ON PETATIAWAL 
‘NMONDINO 3ZISGII ‘ANWN GI ‘WHTI GI 
‘TION 
ag} 
= _/{aWGD S¥On 
‘NMONOIND AZISGII ‘HLAW GI ‘WHII dI 
‘(t] syunqomeus 
} 
} = ({z]syunqomeu yunyd AonIzQ5 
/=« WAOd peaes 03 syunyoS Mou butppe Fo 4seQ T0g »/ 


‘ 
Hf 
_ NOG OVE 
‘kgOm GI ‘WAII aI 

} = []sdoqjswqtt SNOT 

/x wo dojs 03 yUNYD WETI +/ 


— if 
_ Nod OVE 
‘ONaD GI ‘WHII I 
} = [] s30eTTOouqTT SNOT 
/ pezeyzeb eq 02 (TTS UT euO UeYR eXOM) syUNYS UOT_DSeTTIOD WHIT »/ 


a 

ai 
_  @NOd OWd 
‘qq6yazXkdoo_aI ‘Wa'TI_aI 
‘HLOW_GI ‘WaTI_dI 
‘EMOO_aI ‘WaTI_dI 
‘OWWO_GI ‘Wa'II_aI 
‘aWWO_GI ‘WHTI_CI 
‘GHWa GI ‘WaII aI 

} = []sdozduqtt 


(epoo ejezedes y3yM ano wezQTIM eq TTTM AeyA) 3no Aoeq STTF Cyr » 


o'OWSQINE TI/OWeqNg TI/seae 





IFF Specification: Source Code 507 


{ 
5 (90 NanLMa) 34xe 
/()dnueeto 


{ 
1 () Ssuryyo 
‘(atabts du<-qrogresn<-utM>>T) ITEM 
} 

(eu0g;) oTTYM 

‘IsTwdi = eulog 


FTpus# 


/ ((tozrzeEaes) TIIZAT ‘ ,U\S%,,) FAUTAd 
( (eureueaes 
‘syunqomeu 
‘syunyopetdoo * oyureszeg<- [Ys] suqTT 
4zo0s<-[uos]suq tt ‘[wos]swqTtT)eaesueezDs = ToOrzTEAeS) FT 


/ (eweuesaes 
‘,U\syUNYO HAW pue ANYN Sutppe ‘s% se ueexDs eves OF Qnogyu\,,) FqUTIAd 


{ 
/(,U\punoz syxuNyo ONY ON.) FQUTId este 
{ 
as { 
{QxeN Yo<-yUNYS = yuUNnYo 
/(,U\yUnYS ONID & punog,,) sIUTId 
= = } 
((ONaD GI == aI ee eee 
((ONIO AI ‘WHIT aI ‘sxunyopetdos*‘ osureszea<- [Yds] swqTT) xUNYOpuTZ = yunyo) ZT 
/+ Kue Jt syunyo OND petdod puta «/ 


‘(,U\punoz OWWO ON.) F3QUTAd este 

{ 

! (sepopmeta<-Bbured ‘,,u\xT808$ =OWWD,.) F3UTAd 

feqeq yo<-yunyo(, xyunyoburep) = Sureo 

= = } 
((DWWD GI‘WATI aI ‘syxunyopetdoo‘ ozureszeg<- [Yds] suqTt) yUNYopuTZ = Xunyo) ZT 
/» Aue JF yuNYD OWWO petdod puta »/ 


/(,U\:yunyoputz pue sxyunyokdoo zo yseq,,) s3uTId 


* (dos) suqTt) eTTZ FesoTO 
/x MOU STTF SYR SSOTO ued OM ,/ 


} 


/(,u\syunyo butuoTo zoxze,) s3utzd 
(((orTand swan 
‘sqDeTToouqTt? ‘sdoxzduq tt 
4FFT* OFULSSszeg<- [YOs] suq tt) syunyokdoo 


J OWSQINETI/OWseqNg 1I/saae 


= syunyopetdoo * oyuresizea<- [Yos]) suqTt) i) FF 


“ONWO pue ‘dyWO ‘CHWa dn- jes pue pegnduos ATmoeu yATA 
qnq ‘peazesezd eaey om syuNnYyS eYyy SpNTOUT TITA 
YUOTYM WETI Meu e SARS pue 

‘@QTIM TOF Qt uedoexz ‘eTTF peer FAI Sy esoTo 
‘eazesezd 03 WuUeM OM syuNYyoD peszed eyq zF0 Adoo om 


suezboid e 4tim/AZIpoW/peey xrozF eTduexe ue st epod sTUL 
SUONWHOFANS FOPIT# 
{ 


? (00x0 
‘ya’ pywa<- [nua] suqty ‘a*pywa<- [nud] swqTt 
90‘0/dam 
‘00 ‘dew3tqzq<- [nua] suqtt) yrogjseudenataata 
‘(a puwg<- [naa] suqTt ‘m* pyug<~ [nud] suqTt ‘dim ‘dew3tqzq<- [nua] suqTt 
‘,U\PT%=U PTS=4 ‘xTs$$ dz 09 xT¢$ deuqtq 3T@ o3 Jnoqy,,)Snq)q 
} 
/* sseoons x/ ests 
_ { 
!(NRIWM NODA ) BAq 
/ (eweuysnizq’,u\,\s%.\ Usnzq peoT 3,ueD,)F3uTIzd 
} 
( (eureuysnizq‘ [nud] swqTt) YsnzqpeoT = Tore) ZT 
} 
(oureuysnzq) FT 
/* 
MOPUTM 9843 OFWUT YT FTTQ pue ysnzq © PeCT §,30T MON x/ 


/ (29s) Quozqzoy,ueezDS 


ida<- [aos] suqtt da 
/zos<- [aos] suqtt amos 
/* WOaIASeA S,MOpUTM INO x/ idza<-[uos]suqtt = dim 

/» MOPUTM INO ¥/ fuza<-[Yos] suqT? = UTA 

/* ea0qe ()uqTTMoYs TnZsseoons ano Aq dn yes orem oseyL x/ 


/* ATOGMOETA &,UEETDS INS x/ 
/x WeexrDs INO »x/ 


rc { 
S (NWN NMOLTA’ yn) oAq 
/ (eureuuqT Tt ’,U\,\s3.\ Punorbyoeq peotT 3,ueD,,) FQuTId 
} 
( (eweuuq Tt‘ [Yos] suqTT)wqTTMoYys = r0rIe) FT 
/* 
WAaII ue Aetdstp pue peoT x/ 


FFT osuresreg<- [nua] suqtt) i) IT 


! (TIwa_NunLmTa‘ysztou)ekq ((() dAIOOTIW 
FFT osFuleszeg<- [Yos] suqTt) i) Ft 


‘(TIwa NYaLTa‘yszFtou)ehq (( () sAIOOTIV / 
* 
(ewezy ysniq TOF euO ‘eweIyZ useTOS TOF euo) seTpuUeYyY AAI OMA OOTIW x 


x/ 


[awa] suqtt» 
[ads] suqtts 


/» uUsnzq ano x05 y/ / [aaa] swqTty 
/» weerDs zno z0Z x/ / [aga] swqTty 
/* 
@uO ATNezFep ANoO worz sewexzzy WATI HuTyTOM AzNo SZTTETITUL » 
+/ 
imuduy = yoputa<-(ag9q] suqtt 


syyodo gs‘ oyureszeg<- [gaa] suqtt 
SAYOIOST TOD ‘ oyuTeszea<- [aga] suqTt 
syyodord* oyujeszeg<- [aaa] suq tt 


isdoqsuqtTt 
{sqoeTToOouqTt 
{sdozduqtt 


TOWSCNE T/OWSsqNg TI/saae 


p abe 





vices 


: De 


508 ROM Kernel Reference Manual 


{ 

‘ (esegeszegaal)AxzexqrTeso[D §(eseqoszediaI) st 
/ (esequoyaztnqur) AzerzqypTesoTO (esequoTatnqul) FF 
i (eseaxzo) AzezqyTesoTD (esegxzD) 3T 


{ 
‘((OFUINGTI JOnTQs)FoezTs » ENACOIN’ [0] pias aa 7 
(fo] swqtt) sF 


{ 
*(zF4° osuleszea<- [naa] suqTt) AIT 90TT (JF OsUTeszeg<- [NUE] sUqTT) FTF 
‘ (Lada) suqTt) ysnzqpeotun (deuratqzq<- [awa] suqtt) oy 

(Lowa) suqtt) st 


{ 
‘(FFT “osuloszeg<- [Ys] suqTt) AIlSeeTT (ZFF° OFUTOSreg<- [YDS] sUqTT) FF 


FtTpue# 


‘ (syunqopetdoo* og ureszea<- [ads] swqTT) ast TXUNYyooess 


SUONWHOGAWS FOPsT# 


(z0s<- [ads] swqTt) = 
(faos] pena 


‘ (faos] suqTt) wqT FMoysun 


()dnueets ptoa 


ZL ebed J OWSQINE TI/OWSQINg 1I/saae 


{ 

/ (20XZE) BTXO 

2 () dnueeto 

1 (s3/,U\s%.) FquTId Clam sein SER ET 
(zozze AuT‘sy aLxAdn) ekq ptoa 


{ 
iyeezq 
epee 
7yeerq 
:3Tnezep 


/yeeaq 
/ (zozze’,,u\pTg=z0zz0 zequTad dumpueezds,,) squTId 

((o’o 
‘qybyeH<-z08<- [os] suqTt 
‘yaptm<-z08<- [Yos] suqTt 
‘0‘0 

‘zo0s<- [wos] suqTt) dumpueezos=10770e) FF 

/» WeerDs ETOYM eyQ AQuUTId »/ 


/* tad suesu d-TYLD +/ 20TXO eseod 
iyeerq 
‘gnaL = eucd 
[€0X0 SSeD :POXO eSeD :,b, OsED 
/x b zo ‘G-TaLO ‘D-TaLD wo qynb oste * 
(epod) yOuTMS 
*ROAWTIINVA esed 


{ 
iyeezq 
>4Tnezep 
iyeerq 
‘douL = eucd ((zt > Aesnou) 93(ZT > xesnou)) FT 
*NMOGLOTIGS esed 
/x 7ebpeb esoTo e eqetnue »/ 
eeeaine athe 
+ SNOLLNGASOON oy 
(sseTS) yoqu TMS 
? (Bsa) BspAtdey 


fxesnoy<-bSsu Kesnouw 
‘xesnon<-Ssu = xesnou 
fepop<-Ssu =poo 
ésseTo<-5su sseTo 
} 
( (qz0gzesp<-utm) bsy305(, ebesseytnqul jonz4s) Hsu) eTtys 


‘Xesnow ‘xesnouw MiOM 
‘epoo qdaomn 
isseTO ONOIN 
iz0zze@ SNOT 
} 
(pfoa) Ssuryo pyoa 


J OWSQINE TI/OWSsqINg 1I/sage 





: Source Code 509 


IFF Specification 


z e6eg 


(4 OJUWINMTI QOnzTAS) = WATT) i)FF 
/* 
3OnzAS OCFUIWATI SUC SOTTW x 
x/ 


‘ (NRIVM Nunama’,,t\"AzezqyT eszedzzt uedo 3,ueD,) eXq 
(((o/,AzerqyT*eszedzzy,,) Azexqtquedo = esegeszedgar) i) FT 


{(NIWM Nun ’,.a\*Azezqty sotydex6 wedo 3,uep,,) hq 
(((o’, Azezqyy* sopqdexb,,) Axexqrquedo = esegx39) i) FT 


(NGWM NdoLMA’.u\*AzezqyT uoyzpnquy wedo 3,ueo,,) ekq 
(((o ‘,AzezqyT* uoy3ynauyz,) Azexqyquedo = esequofyynzur) j) FFT 


/x setzezqty uedo x/ 
/[t])abze = eweumqTT 


= { 
‘(90 NaotT ‘...) oq 
/ (eesn ‘qybyrkdoo ‘,,u\sgu\sg,,) s3atzd 
} 
((,6,==[0] [T-25ze] abze) | | (SouYNIN>Ofze) ) 5 


‘3OML : asTwa é obze = quuozg 


/I0 = x0zze SNOT 
STION=ouweuq tt» FLACA 
} 


(o62e yy TeYD ‘OHze Auy)uTeuw pfoa 


‘WITT OFUIWATI 3OnzT3A8 
/= SCWRIZ WHTII peqedoTTe zAno r0OqT »/ 


(laszzyou aLxqa 
[]wewou aLxGn 


SuU\FFF COTTE 3,UB),, 
/,a\Azoueu qhnoue 30N,, 


, 
art 
_  NOd OWL 
‘xqOd GI ‘WAII aI 

} = [] sdo3jsuqrtt SNOT 

/+ to doqs oj yuNYD WATI x/ 


— if 
_  @Nod S¥L 
‘ONGD GI ‘WHII aI 
} = [] s30eTTOOmqTT SNOT 
/* pezeyqeb eq 03 (eTTS uy euo ueYQ SOU) sYUNYD UoTROSeTTOO WHTI +/ 


ait 

— _ aNod SWL 
‘qqbyzAdop_ar ‘waTII_aI 
‘HLOW_GI ‘WaTI_ar 
‘LY99_QI ‘WaTI_dI 
‘OMWO_GI ‘WaTI_aI 
‘aWWO_GI ‘WaTI_dI 
‘GHWE GI ‘WHII aI 


a peo ting 1/PeotWa 1/sdde 


} = []sdozduqtt 


(epoo eqezedes yaTM 4no uweqgtIzm eq TTTM AeyR) Ano yoeq eTTF ouyQ » 
S3FIM eM ueYyM weyR dTys ued eM OS ASITT OWWO PUES GWWO ‘CHWH ASTI x 
peqqerz6 eq 03 sxunyo Agjzedozgd WATI »/ 


‘qmmozaz Io0d 


Ht 
NaAAOSNOLSND 


/* moputTm yo edAy x/ 
‘o ‘0 


/= VISTOHXEW PUES YIPTMXEW x/ 
/* AUSTOHUTH PUES YIPTMUTH «/ 
/* Zequtod dew3ta +/ 
/+ peuedo TIT2 TInu 323d ueexos y/ 
/« S5utz3s STITL x/ 
/* szequtod efeur pue jebpey x/ i 
‘ AWALGNE | SLVALLOW| BSAMATSTAVOON | HSAUARU TUWWs | ssaTaaaaog | aowmiowe 
/x moteq sbeta uate sbeta dNodr +/ ‘SNOLLAGASNOW | ATNWTTIINYA 
/* We_YOOTE pue ueqTye ed +/ {t= “T= 
/x YISTeH pue YIPTM x/ 
/x ebpqdoy pue ebpg3szet «/ 


} = auvdu MOPUTMMON 


/6suy, abessontnquyr qonz3s 


qonzqs 
qonz3s 


3OaMeTA 
qzodqsea 


/x  3x0dmetA 03 x0z x/ day 
/*x 3xOAAseA 09 x05 »/ idimy 
/x S8INAQONIAS MOPUTM OF XOZ x/ JUTMy MOpPUTM qonzys 
/* ®INAONIAS UsEeTDS OF zr0Oy »/ ID8y ueez2$ qonz3s 
/-* @ANAONAAS OFUIWATI UT SETQETTEAE OSTe STS spTEeTF SeseyyR - SION +/ 


TION esegeszegaaiy ArerqyT 3onz38 
TION esegxydy AzerqyT AonT38 
‘TION esegquotqtnqury ArezqfI qonz3s 


{,pzeoqdtt> zoz [3tun]o-) eweuuqtt peoqwalrI :ebesn, = ebesn, zeyo 
ty (@TQeqnqyzzastpey ATeergz) g°LeA peoTWaTI, = 3ubyazXdopy eyo 
iuS"LE PEOTWHII :WHASO\n = STeA, TES 

Z SOUWNIW SUTFOpF 


‘(zozze qut’s, 3LxGN)eAq pyoa 
‘(ptoa)dnueeto ptoa 


FTpue# 

/= Ayqjeex «/ { /(o)uznjez } (pyoa) yz0qeyYo AUT 

/x Suaytpuey O/TaLO eoT33eT eTqestd «/ { /(0)uUrn;ez } (pPTOA) WIEXO 3UT 
SOILLYI FOoPrt#H 


wy ddeuqTt/dzzt, epntout# 


/* 
STTFOXEN SOE » 
seTnpow girl Tezeaes yRTm ebexut{T seztnbex 


("290 ‘zo- ‘ToO- ‘d- exXTT) [ATuUN]o- euweueTTZ esn ‘pxreoqdtT{o r0q 


ueezos peuedo Apeerzjte ey3 O74UT WATI SQ speoT ueyqQ - 

MOpUyTM pue ueezoOs eAetTidozdde ue suedo ueqQ - 

epou pue ezts euTMTeEZep O73 WETI ue setxrenb ysazTzZ - 
Yyorys oTduexg 


KEK KEK KKK 


* 
~ 


Wao zeuddeyas ‘D5 16/S0 0° peOTWETI 


| eed a peo NG TI/Peo Na 1I/saae 





vices 


De 


510 ROM Kernel Reference Manual 


!(atabts du<-qrogzesp<-utM>>T) ITEM 
/ (198<-wqTT) qUOTZOLUeeTDS 
1 (UQTT) eTFFTESOTO 
/* 
MOU @TTF SBSOTO TTTM OM OS ‘OTTF SYR wWorF syuUNYO » 
Kue Kdod zo eutuexe 03 pesu 3,0U0p OM - 8Q0N »/ 


£((,U\TRZsseoons wqTTpeoT :peoTuqTt,) nq)q 
} 
(((eweumq Tt ‘wqaTT)WwqaTTPeCT = torre) j) ZT 


JUTM<-UQTT 


TA 
{zos<-wqTT s 


ut 
zo 
/((,u\tngsseoons Aetdstpuedo :peotuqTt,,) nq)a 
} 
este 
{ 
/(,u\4etdstp uedo 03 petteg,,) squtTad 
} 
( ( (Bures<-wqTt 
‘ (HLGSONWXYN ’ SOUPT aU" pywg<-uqTT) NIN 
* (y* pyurg<-uqTt ‘qybteyobed* pywg<-uqtT Tt) XY 
‘(m*puyu<-wqTt ‘yapTMebed* pywa<-uqTt) XY 
‘wqtt) Xetdstpuedo) j) Ft 
/* 
“SpTeTzs ssouy 
O@ZTLETATUT TIT yotym ()AeTdstpuedo osn TTT em OTOH 
*Ketdstp aznoXk zoz da<-uqtt pue ‘dis<-wq{t ‘dam<-wq{t ‘utTM<-wqTT 
‘2O0S<-UQTT EZTTeETITUT ysnu nok ‘os zt anq ‘Ae tdstp 
anoX uedo 03 seutqnoz umo znoX esn prnod nod - e70N x/ 


/ ((Sureo<-wqTy ‘seueTqu*pywe<-wqTy ‘YU pqwa<-wqTt ‘M*pywE<-uUqTT 
{ ‘,U\XTS$=pTepow ‘PTs X PTS X PTS ST WHII styq ‘Azenb zeqze :peotwqtt,,) Snq)q 


/ (eseqoszegaar) AzexqTTSsoTD (esegeszegazaI) FT } 
/ (esequotatnqur) AzerqTTesoTo (SsequoTyTN{AUL) FT (( (eweumqTt ‘uq Tt) wqTfArenb = r0rze) j) FF 


i (esegxs5) AzerqTTeSOTO (esegqxs5) FF 


/* 
” { At OQUT WHTI eyQ ButpeotT ueyQ - 
‘ ((OJUINPII AONTAS) JoezTs ‘uqTT) weyWeor7 Ketdstp umo zno Butuedo uey3 - 
+ (FFF OFUTLSSTeg<-wQTT) AITSCTT (FFF OFULESTeg<-WgTT) IT (pegndwos zo Teez) OWYD pue CHWA Sat 306 02 WHTI Ue Huyxkzenb ysaztz - 
} HutAezysuouwep ere em ereYy ‘TEeAEMOH 
(qT Tt) FF 
} “4t ut WaT ue Aetdstp pue » 
()dnueetTo ptoa ueezoe ejetrdordde ue uedo 03 ()uqTTMoYys esn ptnom nod ATTeUTON »/ 


i ‘(TIwa NanLMa ‘YF FOU) eAq ((()GIOOTTW = FFT OFULOSTeg<-wqTT) i) FT j 
* 
/ (z0z2e) 9Txe ewery TOF STpuey GaAI COTTW x 
/()dnueeto x/ 
1(s/,U\sg.)z9uttd ( (qMwozg)) 939 (Sx)) TF 
} inukay = JFOpuTM<-wqTt 
(xozze Qut‘s, gLxGn) eAq ptoa 
{sdoqsuqTt syyodo js * oyujeszeg<-wqTt 
JsqoeTTOouqTt SYYOIOSET TOO‘ osyulesreg<-wqtt 
- { !sdozduqtt sxyodoad* oyuleszeg<-wqTt 
? (30 NGOLA) 3txXe 
/() dnueeTo /* 
(HWA OATT poztnbexr euwos) ut peysezeqUyT ore eM 


/ ( (z0zx0) t70ggT ‘,U\8%,.) FQUTAd (z0zze) Ft syunyo uwoptqoeTToo pue Azedozd eyy peutyep eaey em eacgy 
-uotqeottdde 


{ ano TOF spTeTF OCFUIWETI Ino dn jes om OTOH 


{ 


! (uqrt) AeTdstpesojTo i 
{ !(TIva NAOLTa ‘weuow) ohq 


/* PEepeeu FT STTFTESOTO ‘SIOTOD sooTTeep »/ / (aqTt) wqTTpeotun ((QGW31O AWANIOI1Tand AWEW’ (OFJUIWATI 3ONTQS) JoozTs) WEYOOTTY 


py abed o°"peo JING TI/PEO TING TI/sace € a6ed O° peo Nd 1I/Pe0 1g 11/saae 





Source Code 511 


IFF Specification 


} (44+T! fo=T) zoz 
23 = Sy‘D FLAGN 
iF Quy 
} /2F% ‘O9n LAGAN (TAF ‘03)XTFFNSICD ptoa 
/w st, XO ,/, eT SYR T9eRzZe Hutzqse Fo yxed setdod styQ »/ 


= { 
(90 NaOLR‘..) oq 
orale 
/ (wqT}9) ysnzqpeotun 
/(eureuz ‘,,u\ ‘sg :eTTZ andqno uedo 3,uptnoo,)zquTId = este 
{ 
{ (dz) esotos 
! (as ‘oureu ‘dz ‘deurtqzrq*uqTt) Sd oak 
(dz) 3 
/(,.M, ‘eueuz) aedog = dz 
2 (2°, ‘oueuz) qeoz98 
‘([t) a6ze ‘eureuz) Adoxzqs 
‘ ([t] abze ‘ourea) xtzznS30D 
‘([t]abze‘,u\ o°sg eTtzs SupqeezD ,,)s30Tszd 
} 
/* WAII pepeot AT{[nzsseoons fh, onee 
$ (NW NUTTY v.) oXq 
{ ( (zozze) r9gaT ‘ouremMgTT ’..U\se=7TOEFTT ‘a \S$n\ WATT PLOT Saeed sa, 
( (eureumqTt ‘waTty) YsntqpeotT = zorze) FT 


/(t]a6ze = eweuuwqtTt 
‘yoqtasgzep : [(z]abze(» abazgn) ¢ (z<obze) = ms 


/x* STPUBHGSI we SCOTTY «/ / (TTIW NUOLW’ (WENON WAasAI) 770gaT) OX 
((QaaIPOTTW = FFT OFUTSSTeA “waTT) ji) FT 
{sdoqsuqtt syyodoqs ‘osureszeg “wqTt 
/sqDeTToomqTT SAYOIST TOD‘ osulesred “UqTT 
‘sdozduqtt syxyodord* ogureszeg “wqTt 
* 
(GHNG SXTT peztnbexz euos) ut peqsereqjutT ore eat 
syunYS uwotT_oeTToo pue Azedozd ey3 peutyep eaey em eACKY 
*seurezz 8 ,uot eoT{Tdde 
INO TOF SPTSTF OFUINMTI 3Inezep dn jes om OrER 


‘(11wa NaoLga’,,Azezqy{eszedzzyq uedo 3,ueD,,) ehq 
(((o’. AzezqtT eszedzzt,,) Azexzqyquedo = esegeszegaar) i) FT 


‘(trwa Naniwa’,,Azezqtt‘sotyder6 uedo 3,ueD,,) ehq 
(((o’,AzezqytT’ sotydez6,,) Azezqyquedo = esegxsd) i) IT 


{ 

‘(40 NAALI) 34xXe 

S(uB\ 8,dT U3FM 8,YD Yndgno of ASTT YORTMS OF 1D, PPY «)FQUTAd 

/(nt\ (zeTFeIQ pue Tepeey on) egTrds peyoerzay ue ,,)F3utad 

/(,U\ (Z0TFeIQ pue Tepeey yRTM) eqtads peyoeazqy e ,)zFquyad 

/(.U\(spz0m zeTTezrQA pue Tepeey on) JeuUTOZ eyTIrds us ,,) xqutad 

/(,U\(spz0m xeTFerQZ pue zASepeey yATA) ZeuT0Z eyTads s ,)zQutazad 

/(,U\(atTnezep) yeuzoz qog : <butyqou> ,,) ;3uTad 

$(uU\ = B5utzqs-qoqtas ezeym ,,) sz qutad 

/(,t\ ,6utr3s-yoqtas eueueTTZ SOWWATI, :IID worz BOrn a SIS 
((,2,==[0] [t->6ze] abze) || (z > obze)) FT 


2 abe 9°D0INE TI/DOING TI/saae 


‘Tog]euweus ‘[og]oueu ‘oweuvq{ty FLAGN 
!TTON=20229 SNOT 

‘dy, 21a 

IMS» eee 


(abzeyy, zeyo ‘obze Aut) utTeuw ptoa 


72 UUUUUOUUGUUUOUOUUUUUUUUUUUUUO Ee () TTI yy / 


ud. = []¥3tMszep aALAGN 


ad 
_ Nod OVE 
‘xqgoa@ GI ‘WHTI aI 
} = []sdoqsuqtt SNOT 
/x to dojs 03 YUNYD WHTI »/ 


/» dde sty z0Z pepeeu euouw »/ -/TION = S3OETTOOUTTTs SNOT 
/* pezeyzeb eq 02 (SETTF UT GUO ueYyA STOW) sYUNYD UOTFRIOETTOO WHTI x/ 


- it 
_ NOC OVE 
‘qHWd GI ‘WHII aI 
} = []sdozduqtt SNOT 
/* 
dde sty x03 pepeeu qHWa ATuo - peqqez6 eq oj sxunyo Aqzedozg WaTI +/ 


{0} = WaTT OFUINETI JoONTRZS 
/~ wey WATI +/ 


ST TON = osegxgso, ArerqyT Aonz4s 
!T7TON = esegoszeggarIy AzezrqtT qonz3s 


{(pyoa)dnuesTo ptoa 
$(® quy ‘sx aLAGN) Aq pToa 
‘(23% FLAN 'O3% ALAIN) XTFINSICO PToa 


1, (eTqeqngtzystpey ATeeza) ¢°Lea OoaWATI. = aybtrAdopy zeyD 
fuG°L€ OOWAII -UAASO\. = sTOAy TeYO 


FTpue# 

/= Aqyeez x/ { ‘(9)urngez } (ptoa) jzoqexYyS Aut 

/x SuyTpuey o/TALD S2F93eT ETAGestd x/ { ‘(o) Urner } (pTOA)waEXO UT 
FOILLWI FOPrt# 


uy ddeuq Tt /dzzt, epntout# 


@STTFJOYeEN eos - saTNpou reyjo Tezeaes yRTM ebeyuTT seztnbey = x/ 
seTNpow eszedzst yANM EsN OF T6-GO PET tTpow 
XINO ITD worz STQeTTeD 


*zeqnduos ebtuy-exopoumop eyQ TOF UoTsIEA sSTUL 
‘ufeuop oTTqnd eyy uT st SETEMAFOS sSTUL 


986T ‘Te wer 
*sqaw OfTUuOzTQ0eTR 
‘meyg ea04g pue uostzzon Azzec Aq o-dumqwai1rI uo peseg 


“seTTS O ut butpntouy z0z 
‘uofqequeseidez TTose qno squyad ‘WaTI ut speez :D0qWMII 


9°D0INE TI/D01NG TI/saae 





vices 


De 


512 ROM Kernel Reference Manual 


{(4o NWOLAU’..U\ ,euweueTTZ MEYOYWETI, :I19 worz ebesn,,) okq 
((,2,==[0] (t-o6ze]abze) 11 (z > obze)) FF 


‘[pz]gnq ‘[og]eweuz ‘oureumq{t, HLAGO 
/TION=x0zz0 SNOT 
y 


(abzey, Teyo ‘obxre Aut) uTeEU pToa 


ORO G BUBB OBO UB OUUBUUUBUUBUUUUUGUUUUURUUBUBURUUBEUBEE Umi. () UFR ge / 


7{ 
_  3NOd OVE 
‘Kgod aI ‘Wa II aI 
} = []sdoqeuqtt SNOT 
/x wo doqs og yUNGD WaTI +/ 


/» dde sty xoxF pepeeu oeuou »/ STION = SQOeTTOOUCTTs SNOT 
/x pezeqqeS eq 03 (STTF UT ENO UeYQ eZOW) sHXUNGS uoTIOeTTIOD WHTI x/ 


“{ 

_  @NOd SVa 

‘aWWO_dI ‘WaTI_aI 

‘GHW GI ‘NAII aI 
} = []sdozduqtt 


dde sty 3 x0z pepeeu qyWO puUe GHWE - Peqqezh eq oj syunyo Aqzedozg WHTI +/ 


{0} = WATT OFUIWATI QOnTAS 
/=» owezzy WHTI x/ 


JTION = esegxzoy AzezqytT Aonz348 
‘TION = esegeszeagaiy AzexzqyI yonz3s 


i(sToou UT ‘sTOD» TYOHS ‘uq, dewata jonzqs ‘eureuy gixan)dewataqeaes SNOT 


i (pfoa)dnueeTS pToa 
i(© Quy ‘sy aixan)edq ptoa 


1, (@Tqe3nqyz3stpey ATeeza) g*Lea MeyoWwAIIL = 3WbtrAdop, zeqo 
uG°LE MBEMOQWATI 7UAASO\. = STOAy TEYD ( 
FTpucs# / (esegxzo) AzexqypTesoto (eseaxzD) FT 
/« Atreex x/ { /(o0)urnqez } (pfoa)  qroqexyo Aut / (esegoszeaggar) AxexrqtTesoto (esegoszedgaar) FF 
/« Suytpuey O/TaLD eoFaazer erqestd x/ { /(o)uanjez } (PTOA) MIGXD 3UT 
SOILLYI FOP tH i (FFF OFULOsred “wqTT) ATeeT AT We SEES Sareea 


nq ddeuqTt/dgzzF,, Opntout# ()dnueeTo ptoa 


------*/ 
OSTTJOXYEN ees - seTNpou reYQo Teresaes yRTM EbexuTT sertnbey { 
seTnpou eszedzzt YANM OsN TOF [T6-GO PETFTPow / (@) a7xe 
KINO ITD wory STIETTED ‘()dnueeto 
£(8/,t\s$u) FQ ( (8%) 3998) FF 
*zeqnduos ebhbtuy-ezopommop eyQ AOF woTszeA sTYUL } 
‘ufeuop oFTqnd ey UT ST STeEMAZTOS STUL (® ut ‘sy abxan) eXq ptoa 


986T ‘TE wer 
“sqay oTuoTQOeTE { 
‘meys eaeqs pue uostazzoy Azzec Aq o'meyWATI uO peseg 2 (zz /09) Adoz3s 
{ 
(deuzotoo Aq pemoTTos fs = 23 (,:, == 9) JT OSTO 
‘seuetd mex) OTT MBI ANO SOEQTIM ‘WETI UT speer :MeYoIWEII is = 33 a == 2 at 
fyeezq (9 == 2) FT 
f++Sy = 


1 a6eg o°"MEYOMNG 11/MeCHOMNG 11/sade o°OOING 1I/D°1lNG 11/saae 





Source Code 513 


IFF Specification 


/* 
sse0ons TOF QO surnqey 
(WHII we AOU) EeTqeAOTOD pue seueTdatq mex Ano seqTIM 
‘zequtod eTqeqzojToo pue ‘eanjonaqs deuwytq ‘eweueTTy ueato 


(eTqe_zOTOD pue seueTd mez se) dewatgeaes 


= { 
= £090 NWAGMA' wn) OAq este 
‘(NaWM NaOLwa’ (rorTe)zzegaT)eAq = (IOTTE) FF 


{ 
‘ (UqTt9) Usnzqpeotun 


‘(szoToou-uqTy ‘eTqeqzojToo‘uq Ty ‘dewatqrq'uqTt ‘eureuz) dew ytqeaes=1r07790 
‘(eweuz ’,u\ 5% eTTZ BurqeezD ,,)s3QuTIzd 
{(gnq ‘eureuz) 2e0z48 

‘ (yadeq<-dewytqzq"wqTt ‘Ps, /FNq) FQuTa@ds 
1 (.X, ‘eureuz) qeor48 

/(guq‘eureuz) qeor48 

£(q* pau wqTt / Ps, ‘FNq) FQuTads 

7 (uX,, ‘oureuz) Jeor4s 

/ (ynq ‘soureuz) QeDx748 

/ (a puma “WATT ‘Ps, ‘3nq) FQuTzds 

i (a° 4 ‘eureuz) Qeozr3s 





i(,90eT*, ‘oureuz) geozQ5 (gowr 3 BSureo‘wqTt)35T 


{ 
 (esegxzy) AzezqyTIesoto (esegxID) TT /(,0T'. ‘ouweuy) QeDzQ45 este 
/ (epseqeszegaar) AzerqypIEsoTD (eseqeszeg aa) FF $(aFa°. ’Oweuz) VeorQs (SaIH 3 Sureo-uqTT) 3st 


‘(FFF OFULSSTe” wWqTT) AITECTT (FFT OFULSsTed “wWaTT) IT /(,qye*,, ‘eueuz)Qe07Qs (3LTUGaTVH WaLXa 9 Sureo-uqTT) IT 
} (,wey’, ‘oweuz) qe0zQ8 (WWH 3 Gureo-uqTT)ZzT 


()dnueeTo ptoa 

é([t] a62e ‘oureuz) Adoz35 

{ } 
? (9) Qyxe /* WAII pepeot At{nzsseoons »/ SsTS 

/()dnueeto _ { 

(8/,t\8eu)FQUTId ( (84) 998) FF { (NEW NMALTA’ 1.) oAg 

} ! ( (z0zz@) zregTI ‘ouewugT Tt ‘,,U\sy=TTEFTZF ‘n\S$u\ WATT PET 3,0e),) squzrd 

(® qut ‘s» gnxan)eXq ptoa } 
( (eueuuqTt ‘wqaTT3) YsnrqpeotT = z0770) FF 
{ /« 3% Aetdstp 03 peeu 3,Uop em eDUTS Ysniq & se peoT x/ 


‘(SLIM WAFAGI > TO & 0 =< qu)urngez 
1 (@TTF) ©80TO 


/= dea zojTo> eaes x/ /(Zx(yqdeq<-uq>>T) ‘sToo ‘eTTsZ)e3FIM=quU (o<qu) 3F 3 _ 
{ /« STPUCHAII Ue SOTTY «/ / (TIVa NUNLM’ (WANON WaAIsTI) TIETIT) OAq 


‘yeezq (eztstd>qu) FT ((()d4aI90TTW = FFF OFUTOSTeA “UqTT) i) FF 
f(eztstd ‘[(t]seueta<-uwq ‘eTty)eqtImM = qu isdoqsuqtt sxyodo 3s‘ osyuresieg “wqTt 
} is qoeTToowqtTt SYAYOROST TOO" osyuloesszeg “wqrtt 

(++ 4 /qyqdea<-uq>t ‘o=t) x0F !sdozduq tt sxyodozd* osyureszeg watt 
/smoy<-uq,moyzegseqig<-uq = eztstd 
{ 


/(t]a6ze = eureuuqTt 


“= $ (GHWNG EXTT peztnbex euos) uy peqsezequT eze OM 
/« ©TTF-peotT e uedo Auptnoo ,/ ! (QomaT LNAITO) uznjez syunyo uotqoeTToo pue Azedozd eyy peutyep eaey em SAcgy 


/ (aweu’,u\ 56% uedo 3,uptnoo ,) zs qutad *“seuezz s ,uotqeottdde 
} ano TOF spTeETF OCFUINATI 3Inezep dn jes om er0H 


= (0 == ©TTF )3T 
‘(@TIGMEN FGOW ‘eureu )uedo = ETTF SNOT = 
{(TIvad Nuotma’ArezqtTeszedzzy uedo 3,ueD,,) oq 
‘eztstd’qu SNOT (((o/,AzezqtT eszedzzy,,) Azerqyquedg = esegeszedgaI) i) FT 


!} ZYOHS _ 
} /(1rvwa Nana’. AztezqtT*sopyder6 uedo 3,ueD,,) oAq 


(sToDU AUT ‘’STODy LYOHS ‘Woy dewata yonzys ‘eweu, aLxAgn)dewataeaes SNOT (((o’,AzezqyT’ sotydez6,,) Azezqyiuedo = esegx35) i) FT 


¢ abed o°MPYO}WNG 11/MeEHONNG 11/sade zabeqg =o" MBYOWW A TI/Me YON 11/Saae 





vices 


: De 


514 ROM Kernel Reference Manual. 


euwezz O43 FOF OTPuUeY FIT O43 OOTTY x 

x/ 
isdoqsxase sxqodojs "osyuyeszeg<-xase 
JsQDdeTTooxase = sAYORDET TOO" osyulesreg<-xase 
‘sdozdzase syyodord* ogureszeg<-xase 

/* 

*xao@ uo dojs 03 QUeM OM » 

* (GHA ©XFT peztnbez euos) ut pejsezequyT eze Om , 

syUNYD uofADeTTOD pue Azedozd eyQ peutyep eaey em eACaY « 

*uozqeottidde 

zno xoF spTeTs osurxXASAYbt_ ano dn jes om oT0H » 

+/ 


= a {(TIva NaoLTy ‘weuou) ofq 
((Cawato aWan|OITaNd aWaW’ (OFUIXASQUSTA 3ONIAs) JoezTs) WEWOOTTY 
(~ OFUIXASIYSTaA QONTAS) = EAsO) j) FT 
/* 
qonzqs osurxASaubtg_ euo SCOTTY » 
a/ 


(NVM Neotma’..a\*AzerqtT eszedzzy uedo 3,ueD,,) ehq 
(((o/ .AzezqtT* eszedzzT,,) Azexrqy¢rTuedg = eseqeszegsaI) i) FT 
/* seTzerqTT wedo 


‘{tJabze = eweuxaso 


= { 
(90 NaALMI’ 1.) eAq 
2 (ebesn ‘qybtzkdoo’ ,,u\seu\s%,,) FQatzd 
} 
((,2,==[0] [T-o62e] abze) | | (SpaYNIN>Obze) ) TT 


‘gOuL : asTwa 2 obze = quuozyz 


‘To=rT0zzTe ONOT 
#300 SNOTN 
*TIQN=eueuxase, ALXGN 
} 
(aBbzeyy rey ‘ohbze Aut) utTew ptoa 
/* 
NIWA + 
a/ 


‘TION = Eas0, o3uIxASaySTa 3ONIT3s 
/= OFVIXASAYSTT peyeooTTe xzno z0g «/ 


{lusztow anxan 
[]wewou aL7G0 


FyU\FFF SOOTTS 3,02), 
/,a\Azoueu q5noue oN, 


“{ 
_ NOG SVL 
‘Kgom GI ‘xXASS AI 
} = []sdoqsxase SNOT 
/*x to doys oF yUNYD XASB «/ 


‘ 
“{ 
_ NOG OVE 
‘ONNY GI ‘XAS8 CI 

} = [] sq0eTTOOxASe SNOT 

/*x pezeyzeb eq 02 (STTS UT SUS UeYQ eTOU) SYUNYD WOTIOSETIOD XASB x/ 


— it 
_  SNOd OWL 
‘aqbyxXkdop aI ‘xase_dI 
‘HEAW_GI ‘XAS8_dI 
‘asTa_aqI ‘xaSe_dI 
‘WWIW_aI ‘XAS8_dI 
‘SWWN_GI ‘XAS8_dI 
‘AGHA GI ‘xAS8 CI 

} = []) sdozdxase SNOT 

* 

peqqex6 eq og syunyo Ajzedozg ae 


*qmmozz  ‘TOOE 


'T TON = eseqxzo, AzezqyI 3onz38 
ITgoN = esegoszegaary AzexzqtT 3ONI34s 
/* BTeQOTH »/ 


/,eureuxass xaseteta :e6esp, = ebesny xreyqo 

‘. (eTaeanqFzastpeu ATeeza) s“Lea xaseketa, = aybtzAdod, zeyo 
aG°LE XASBAeTA 2UHASO\. = STOAy TeYO 

Z SDUWNIN eUuTsFEPH 


‘(eumToa quomn ‘pofzed ONOTIN ‘ezTss SNOT ‘TQdures, ALA 
‘TOTE, OFPNYOI 3OUIAS ‘QOTE, OCTPNYOL 2ONnz3s) eTdwesStqheTd, Otpnyor yonT3s 


:(KeTep ONOTN ‘eumToa GYOMN ‘©3707 ONOT ‘SAPRD0 ONOT 
‘ASG, OFUIXASIYSTY_ ONTAs) etduesheTd ONOT 
i (P}oA)OFPNYESOTO PTA 
/ (pfoa) ofpnyuedo ONOT 


{(xasey OFUIXASIUSTY OnzAs) eTduresmoys ONOT 


/(xasey, OFUITXASIYStT_ yonzX4s) Apogspeotun ptToa 

/(xasex osUIXASIgST_ Aonz34s) pogspeoT SNOT 

{(xasey OFUIXASAYHSTY_ AONTAs) oTdwesgpeotTun pToaA 

/ (@weUeTTS* ALAGN ‘Kasey OFUIXASIGHTa QONTAs) eTdurespeoT ONOT 
(x guxa ‘[]3sep aaaq ‘t ONOT ‘[]eornos gizAg)xOedUATa gqLAG 
‘(Llasep azaq ‘u ONOT ‘[]e>znos guxa) xOedunG PToA 

/(z0zze qut‘s, g3LxAaGn)ekq ptoa 

{(pfoa)dnueeTo ptoa 

/* SUOT_QOUNZ ANO A0F sedkj0Q02d x/ 


FTpusz 

/« Atyeex «/ { ‘(o)urngez } (ptoa) ytoqeyxYyo WUT 

/» Suttpuey o/TALO eo7aaer etqesta «/ { ‘(0)urnqez } (pToA)MiaXD UT 
AOLLIWI FOPsT# 


<y*soqord qtTe/qtTo> epnTout# 
<yeseqxzs6/sotydezh> epntout# 
<Y"oseqoexe/Dexe> epnTout# 


vy ddexasg/dzzt,, opntout# 

TERRE ERE RARER MAME REE ERE EO OR EO EI EE 
“ie STTFOXeW ees - solTnpow TIT TeASASS YAM ebexutt seztnbex 
WD SvoO - seqou AeTd 03 ¥ oszedszzT YRTM OSN TOF T6/SO PETITPOW 


“ufeuop oftTqnd eyQ ut sft eTeMAZOS sTYyL 
“sqzw ofuorq0eTgZ ‘sexey eaejs Ag 


SeuertzZ “eTTF aa we worz eTdues punos Aetd pue peey 


* 
RM MR RE HOR I I NOE EE RA RR MRE ER IR IE BE >°xassAetTa xx/ 


1 o6eq 


o°XAS8ABId/XAS8AC|d/Sade 





IFF Specification: Source Code 515 


/« spueu0D TOF SYDOTA OI OF s29d x/ {{T1ON} = [ENOOIV]OTex OTpnYOI  onT4s 
b LNOOIY eUuTzEPH 

IS689¥SE WOOTO Twa eutzepH 

ISVSELSE MOOTO OSLN euTzepH 

/* TWd S689¥SE ‘OSEN SPS6LSE SenTeA eseyy - O90N x/ 


‘fzt]zed qaoma 
/» Kouenbezz yooTS weqsks z0z peqsn{pe spotzed ,/ 


‘{ 9%% ‘ove ‘psz ‘oLz 
‘98z ‘zoe ‘oze ‘ove = 
‘o9e ‘ose ‘vow ‘ezp } =[zT]osqu zed quomn 


/* 
so tdues 
soe Tdues 
sotdues 
so tdues 
sotdues 
sotdues 


ZHOO’€602 
ZHOS “9POT 
ZHSZ°E7S 

ZHEO" T9Z 

ZHT8"OET 

ZHOD'S9 


H{ 8’p’2‘T } = [] Teuwueqgotym aLxAGn 
/ 


zexyeqg ueq Aq epoo uo peseg 


qe Bupqzeqs eTteos z0z spotied y/ 


* 


sse00ns TOF O surN_eY 
sqjsonbez oI Zz ‘Teuueyd otTpne euo z0z soTAep oTpne suedo 


KKK KK 


otpnyuedo 


* 
~ 


{ 


i (z0zze) urN_eT 


‘(fe +8]30q/ (9+8]30q 
‘[o+e] nq‘ [pt+e]3nq’ [e+e] 3nq’ (z+8] sng’ (t+8] 3g‘ [o+e] snq 
‘aU\""" PTES PTES PTES PTES PTES PTE PIES PTES U\.) Fauzad 
‘(fel3nq‘ (9]3nq‘ (s]3nq/ (yl snag’ [e]snq’‘(z]3nq‘(t]3nq’ [o]znq 
‘,PTES PTES PTE PTES PTES PTES PTES PTES = EREqu\,,) F3UTIzd 
/ (eumfoa<-zpya ‘,,XTsxXO=eumToau\,,) FAUTAd 
{ (uofssezduops<-zpya ‘,,pTz=uotsserdwuoosu\,,) squTzd 
1 (2A299090<-zpyA /,PTZ=eaeg{0090U\,,,) FQUTId 
/ (pegzegseTdues<-zpya ‘,,plTy=oeszeaseTduesu\,,) sQuT@d 
‘ (eTOADTHAeaseTdues<-zpya ‘, pTs=eTOADTHTeaseTdwesu\,,) sQutTzd 
/ (sotTdurestHqeedez<-zpya ‘, prTy=soTduegtyjeodeau\,,) s3utad 
‘ (setdurestHjoyseuc<-zpya ‘,,pTsy=seTduestHjoyseuou\,,) s3uTId 
$(,20FUI WaHAT\U\,,) FaIUFazd 


/ (eweu<-xase/’,,5% 2 SAYNU\,,)s3UTId ( [0] eweu<-xase) FT 
/IPUA<-XASEF = IPYA 
/x owezy xase 2zno oj (Aue 37) GWYN pue udHA petdoo eTdurespeoT ,/ 


((eTdures<-xase = ynq)j)3T 


! (AoWIT_LNAITO) urnqez 
(xasej) ZF 


‘(MOWAT BNAITIO) uznjex 


fIpyAy TEpeePgeoToA 
‘30qy ALA 
{JQ = r0OxzIe© ONOT 
} 
(xase, OFUIXASZYST_ JOnzTAs) eTduresmoys ONOT 
DRE ROR OO OOOO UO OOO ORR OR ORR 


* 
()atduegpeoy But TTeo zeqze uoTAewrosuy eTdues moys » 


a XASB8ABId/XAS8ABid/Sade 


p abe 


* 
JOGO U OU UOUGUGUBUOUBUUBUEBEEoE. () 2TUUeSMOUS 4%/ 


{ 
(eseqoszeqgdI) FT 


{ 
‘((osurxASaybtg_ yONTAs) FJoezTs ‘xase) wepoeerg 
‘((.t\osurxasaubtg_ eezz 03 ynoqgy,,) nq) aq 


/ (osegeszeggar) ATeIQTIESOTO 


(FFF OFULSSTeg<-xXASO) FT 


(FFF OFULSOSTeT<-xXASS) AITSOIT 
$((at\gaTeezg 03 Qnoqy,,) nq) aa 


/ (xase) oTduespeotun 
‘((,.a\etduespeotun o3 ynoqy,,) nq) aq 
} 

(XaS9) ZT 


} 
()dnueetT> ptoa 


{ 
/ (x0z2x8) 4Txe 
‘() dnueeto 
£(s/,U\s¢.)zautazd ((qmuorg)) 99 (S¥)) FT 
} 
(zorz® QuT‘’sy aLAGn)eAq ptoa 


= { 
(90 NYALM) 3txXe 
/()duueeto 


! ( (zozze) zzEgaT ‘,U\s%,,) FQUTId 
esto 
{ 
/(,u\eoTtaep otpne butuedo zozze,) FQuTId este 
{ 
7 ()OTpnyesoTo 
{ 
{ 
1 (0S ‘09 ‘L ‘300 ‘xase) otduesketa 
‘(0g ‘09 ‘py ‘300 ‘xase) otduesketd 
£ (0999 ‘9/300 ’xase) oTduegketg 
} 
(++990 /eab D090" 2pPyA<-xXASe > QDO /O=300) TOF 
} 
esto 
/= Joumry{suyt ue eyxtT at Aetd estd x/ 
{ 
£(0‘p9 ‘T-‘0‘xase) eotdueskerta 
} 
( (sotdures tHqeedez * zpyn<-xas0j) 99 (soTdurestTHIOYsSeuo " ApyA<-XASO) 73 
(vegzegsetdures * 1pyj<-xAS@) 99 (T==9ALIOOAO * IPYA<-XASS) ) JT 
/« (T-=e30u) yons se ay AeTd ‘qoezzo punos e st sTyy YUTYR om FI * 


(((Q)otpnyuedg = zoxzze) {)3T 
/ (xase) otduregmoys 


} 


(((eureuxase ‘xaso) eTduespeoy = rorze) j) FT 


/(TIwa NanLea‘yZFtOU) exq ((() AAIOOTIV = FFT OFUTOSTEG<-xAsSD) j) FT 
/* 


¢ e6ed a XASBACId/XAS8AB|d/Saae 





Devices 


516 ROM Kernel Reference Manual 


eq Aeu FTEsSAT Qoyseuo oyy ZeYR AuNoOddSe OUT EeYeQ Jou 
seop pue ‘snouozyouds ‘otastiduys st BSuyuyy zoz Aeteq Fo esn - 
(3STA pue WWLY Op jou seop euTqnozr eTduwexe eTduts styq - se 70ON 


“pqe@ ‘T eaRQDO se 
qseTTeus 3xeu ‘9 eaeQD0 se XASS UT eTdues eAeQD0 AsehzeT sesn 
(#a) TT pue (5) 9 weemqeq senTea ejou sqoedxq 
sseqou BSupxketd wey 


Ktsnotaeizd pettes ()otpnyuedo [nyssesons seztnbey 


(T- ‘0 03 eqAou pue eneQD0 Yes) Zoezsze punos e Aeta uo 
puopes e so syq0g/AeTep roxy eneQDO UT eQoU e& AeTd 


KReEKEK KKK KKK KKK 


* 


JEU OUBOOOOUEEOOOOUUUUBOUUUUOUBUUURE ures () oTdueskeTd xx/ 


{ 
(320d) ZT 


{ 
pearees 
(++ JENOOTW>A /0=%) OZ 


{ 
‘asiIwa = peuedoasp 
‘(Lolote (% qasenbeyor qonz38) ) eotaeqesoTo 
} 
(peuedoaep) sT 
/« sqsenbez otpne Bbutpueqsqno ou eaey eM MOUY OM - SION ¥/ 


‘TTAN = qr0od =‘ (320d) qz0gej°eTSq 


‘TION = [y]ote ‘([x] ote) oLaxTe3eTeEd 


i((.a\t*tepzaep ofpne SutsoTo,,) nq) q 


iy 7 
QotpnyesoTD proa 
/x 


szeqjutod qno [tnu ‘otpnyuedo Aq peuedo se eDtAep oTpne esoTD » 


* 
OTPNYWeEsoTD x/ 


{ 
/ (z0zz0) uzN_AeEZ 
{ 
‘(QofpnyvesoTo 
/(zozze’,,u\pT; deqs 3e 4no pezozze otpnyuedo,,) s3utzd 
} 
(10IZTE) FTF 
= qnoTTeq 


JLolotes = [y]otes (++4% /ZNOOIW>4 /T=%) z0z 
/* Sysenbez oTpnNwoI ZeYRO ORAUT “DRe ‘UOTAeDOTTE Teuueyo ‘sbeTzZ eyQ SUCTO x/ 


{ ‘{qnotteq 0706 ‘/g = zorze } este 
‘gnaL = peuedoaep 
Lolote (x asenbeyor 3onz3s) ‘10’, e>;Aep*oTpne,,) eotaequedo) j) 3 
[arntnn nena roan Bree os weer area acne <7 #/ 
/x JTeuUeydD eS SZedOTTe pue eoTASp OTpNe ey uedo x/ 


(( (To ‘ 


yqbuelt_eot<-[o]ote 
eqeq_eot<-[o]ore 

_ Aeyootty_eot<-[o]orte 
s6eta ot qseonbey eot<-[o]ote 


/ (Teuweyotya) Foezts 
/TeuueyotTya 

— 70 

?LIVMON dOldw 


a" XAS8ABId/XAS8AB|d/Sade 


g abey 





pueumiog of“ ysenbey eot<-[o]ote 






!3LWOOTTW GNDaY = 


/s ‘st sTeuueyo Fo ASTT ano Huot Moy sTTe9 yybueT_eot x/ 
/* “quem om sTouueyo eyg BbutastT Aezze eyq 03 rzequtod e st eqeq eOT x/ 
/x"3USsS spueUMIOD TeYRO TTe Tox seaTh qq Ay oyR Osn Asnu eM “speeDdons »/ 
/% YOFRESOTTE Sy JF EPtaep ofpne ey Aq uy peTITs eq TIM AeyooTTW_eot x/ 
/* *sBets OI eyQ rox pesn st sheTa_of-ysenbey_eot x/ 
/* ‘OL XOF pPTEeTZ pueumoo oyA st puewmsop ot-ysenbey eot x/ 
/*°SQ WOTF TEuUeYS eyR TeSYSs TTTM eouepeserd reyqbty e eaey eYR SoTASeD = x/ 
/*x OfFpne eyy esn 03 Bbutyse syseq Auy_‘eotaep_otpne eyA Jo esn ano jo / 
/» (Aqyzotad) eouepeserd eyy sjes tid UT“ epon_uur-ebessey_ot*'ysenbey_eot x/ 
/» ‘°yx0d K{tdez e Jo ssezppe eyQ st qzogX {dey uu-ebessey ot‘ ysenbey eot 4/ 
/* IUOFQEDOTTE Teuueyo Toy YOOTC O/I otpne eyQ dn yes 










{ {qnotteq 0306 /z+y = zozze } 
((((oFpRYOL 3ONnzAS) FJoezts ‘yz0d) o1gx Fe VESTN (x OTPNWOI QOnzAs)=[HA] OTe) j) FT 
} 

(44% FENDOIW>Y /0=4) TOF 





fqnotfeq 0706 /{T = xozz0e } 
(((0‘0) 3roaaQVezD=R20d) j) FT 


fears eaerese se ess eae Sasa S san ears Rae eae ara aiatenat a/ 
/* spueumo> ino 03 AtTdez ues eotaep ofpne ey os yzod AjTdex e e jeer +/ 
JercconeRos cassie Saal ewer nannn- / 





Os 
!(({a] zed/4',, pts=[PT%] zed,,) nq) a 
_ 2 f‘potzed = [yx]zed 
{MD0TD OSIN / ((T << MOOTO OSEN) + (A90TS » [4] O8Qu z0ed)) = potzed 
} 

(+44 {ZT>4% /0=%) TOF 

/x Yo TD weqsks uo peseq eaeqQDo |UO TOF senTea potzed eqertnoTteo ~/ 


J(YOoTO /,U\PTZ=AOoTD ‘suoTAeTNoTeo potzed rzog :oTpnyuedo,,) yquTad 
{ 


‘(eseaxsg (, AxearqyT qonzys) ) ArezqTTesoTo 
!MD0TO ODSIN = ATS 





= este 
iMDOTO ‘Twa = AoTo 

(Twa 9 sbetaketdsta<- (eseaxgo( eseqxsD 3ONTAsS))) FTF 

} 
((10‘,Azezqtt* sopydesb,,) AzerqypTuedo=esegxy) JT 
/s-- SI a a Fanner me a Ptr fora Fee eee a Sere Fae te eee ey ee rege ee SS Se ee af 
» Ki{butpropoe Aueqsuod yxooTD yes pue OSIN IO Twd ere om FT weqsks oy ASW « 
/ / 


aa-------- wanna nn nnn nn nnn nnn nnn nnn nnn nnn nnn nnn nnn nnn nnn nnn nnn 


(peusedoasp) FT 






‘ (T-) wrnqez 








cet Quy 
ipoyzzed = sNnomn 
?Jo=x01720 SNOT 


fesegsksy, esegoexg jonzQ4s uzeRxe 


} 
()ofpnyuedo SNOT 






{¥D0TD OSEN = ¥20T> SNOTA 
/peuedoasp ‘Too 
fqzody qzoa6sy Q0nI35 


/» Kzesseveu Jt ebueyd pue wd TOF YOoyD TITM x/ 


/« K{dez ued eotaep eyQ os yzrod e& 03 ZeQUTOd x/ 


a" XAS8ABld/XAS8AB|d/sade 






g e6ed 


: Source Code 517 


IFF Specification 


fjote = [(ubezjote 
foofte = [bezJote 


+ (TION) wrnqez ((3IENWSXYN > OzTSs) || (TOTei) 11 (OOFeI) TF 


/s sexepuy jsenbez ofpnyol 3xeu pue quezinod ,/ ‘{T=ubez ‘o=bex qut 
fezts = SNOT 
f[z]ote,s OTpnYoI 2onz35 
} 
(eumqtoa quomn ‘potzed ONOTIN ‘eztss ONOT ‘139dues, ALAG 
‘TOTS ,OFPNYOI JONITAS ‘OOTey OTPNYOI 3ONTQs) eTdmeshtqheTd, oTpnyoL onTQe 


DRAB REARS EEA EEE ARMA 
(x0zze) euoU ZT TION 20 


qno TItas st 3e4Q Asenbez ofTpnyoIr eqQ 03 reQUTOd suznjex 
sSYOOTA Aysenbezoy oTpnyoI esn-o37-Apeez omg 03 sxequTod squem 
MBZT < setdues yQTM Teep oj etdwesXketd Aq petteo 
FAG O OOO UOURUOOUUOOURUOUUUBUOUOUODUBUUE nes ()oTdiresbTqheTd 44/ 
{ 
/ (.t\euod,) s3utazd 
{ 
* (T3n0e) O13teM 
? (T3nee) OTATOGy (0 =< 930U)FT 


} 
(T3N0e) TF 


/» mou qt doqs ‘ejou e& ZT x/ 


‘(o3no0e) OTateM (O3N0e) ZT 
/* 3RO EAE TIT389 OM sqsenbex Aue zoz 3TeEM »/ 


/» 8ej0u z0z Buywty epnzo y/ =! (Aetep) ete (AeTep) 3 


{ 
{ 
/ (eumToa ‘potzed ‘eztez ‘qeedexz’ [eJozse’ [z] ore) etdureshrqhetd = TAanoe 
[z]otes = Bes 
este 
/« ABZI< setdues TOF sy epod esed esTe sty - SION x/ 


‘((LzJoze=tqnoe) (, qsenbeyor 30nz38) ) orutbeg (SIANVSXWW => OZTEI) TT 
/x (seTdues qsou ‘et) wE8zZT => eTdues joyseuo roxy eseo eTduts x/ 
} 

(ezqtex) ZT 


{ 
{ 
{ (eumToa ‘potzred ‘eztso ‘joyseuo’ [T]oFe’ [co] ote) otdueshtqhetd = ojnoe 
‘[o]otex = on 
esto 
/* ASZI< setdues xroz st Epod esed ESTOS STU -— OION «/ 


‘((Lo]oFe=o3n0e) (¥ asenbeyor yonz38) ) orutbeg (HIGHWSXWN => ©ZTSO)ZT 
/« (se Tduwee jsow et) sZt => eTdures joyseuo zoz esed eTduts y/ 
} 


(©zt80) ZT 


!(potzed ‘seToXp eot<-[T]ote ‘eztsx ‘seToAD eoy<-[o]ote ‘eztso 


‘a’ 'ptg=zed ‘oAD pTos z0F pte wot y ‘okD pTO% TOF PTS weT O euog Huta2e95,,) squtpad 


g abe a XASBAPId/XAG8APid/Sade 


Z 36eg 


/* Bswitdey ey 306 eyR 206 pue arem 03 ()OI3TEM x/ 
/* UF YSTUTZ OF punos eA Toy QTFemM pue deets 07 oD ¥/ 
/» ()oruy6eq Sutsn punos e A7eAZs 02 pueUMOD eYyQ pues «/ 


/x peddoyjs ttqun jeedez »/ ‘/o= 
seumToOA= 

‘potzed= 

/eztsi= 

/qeedez= 

*TOAUGd JOTAY= 

‘SLIM GNO= 


T= 
feumqToa= 
{potzed= 

{OZTSO= 
/3oYseu0= 
“IOAMTd JOTAY= 
*aLIUM CNO= 


seToAD_eot<-[zJ]ore 
eumToa_eot<-[zZ]oTe 

poyreg eot<-[zJjote 
yqbuey_eot<-[z]ore 

a eqed_eot<-[z]ore 
sbeta_of  ysenbey_eot<-[zJote 
pueumog of ‘ysenbey eot<-[z]ote 


seTokp eot<-[o]ote 
eumToA_eot<-[o]ore 
potzed_eot<-[o]ote 
yqbuet_eot<-[o]ore 

bs eqeq_eot<-[o]otre 
sbeta_ot ysonbey_eot<-[o0]ote 
pueumoy of qsenbey eot<-[o]ote 


(@3ez BuyTdues ueatb) /xOoTS = potzeg ect yes 

‘eqez Buy tdues ueatb e ye etdues eyq Aetd of Quem nod ZT 

eTdues ey, eedez_oj sewty Aueu moy sTTe3 seTOAD bot 

yybuetT ey3 seath yabuey eot ‘/etdures ey3 03 squTod eyeq eoT 
‘etdues rmno ey YAM eumToa pue (peeds) potzed 

eyQ 2e6 UeD OM Of TOAUTd JOIAY OF Qos ore sheTgZ of ouL 

(yq0q peeu jou Aeu em Qnq ‘eseo etduts zoz Apeez [Te) 

qeedez zoz euo pue Aoyseuo ey3 z0z Asenbez euo dn yes 

“SLIUM GND buysn etdues e Ketd 03 syooTq O/I ofpne dn yes 


/((eztsz ‘3eedez ‘eztso ‘joyseuo 


‘,U\PT% OzTsS XTZg Qeedexz ‘pty; ezTs xT%$ RoYseUO,,) bnq)a 


eztsz 
qeedez 
ezTso 
qoyseuo 


/ [=aeqQD00] seztsi<-xaso 
/ [eaeqo0] sduresz<-xaso 
/ [eaeqoo] seztso<-xaso 
/ [eaeQD0) sdureso<-xaso 


‘yg = eumtoa (99 < eUMTOA) ZT 


40 = @ABQD0 (8ABQD099°APYA<-XASO < EABQDO) JF 


/« Ofpnyuedo Aq dn jes eTqeq x/ ‘[ejou]zed = potzed este 


ipegzegsetdues ‘rpuj<-xase / YOTO 


TTION=T3N0ey 


potzed ( [- == e jou )FT 
‘Q=eQ0uU (TT < e30U)ZT 


/(T-)uznqez (peuedoaep;) st 


fqeedez, ‘joyseu0, ILA 


feztsx ‘ezTso SNOT 
‘poyzed SNOTO 


‘TIQN=03008,% OFPRYOI onz3s 
/* 8 qsenbex Buypuejsgqno 09 sxzequtod ,/ 


} 


(AeTop ONOTA ‘euMTOA CYOMN ‘eR70U ONOT ‘eaeqD0 ONOT 
‘XASOy OFULXASWYHT_ WONIAs) oTduesketa SNOT 


ZLOTET AIANYSXYN SUTFIOPH 


/« M8ZT St ysenbex or euo ut eTdues etqeAetd xen x/ 


J RRR A EERE EEE REE 


skejep snouozyoudse eqernooe ezou TOF EDdTASP' TEUITTQ ESN 


-Xejtep eyq ueyQ zebuoy, 


I XASB8ACId/XAS8AL|d/Saae 





vices 


: De 


518 ROM Kernel Reference Manual. 


/3TIZGON = xozz08 
‘(.a\xase ue 3on,,) ebesseou 
} 
este 
{ 


{((ezftsez ‘3eedez ‘eztso ‘Aoyseuo 
‘,U\PT% SZTS XT¢$ eedexr ‘PTs ezTs xT%$ JomseUO,,) hnq)a 


toXods = [300] sokods<-xase 
‘0 [300] sduresz<-xase este 
fqeedez [300] sdureex<-xase (ezts21) FT 
Jeztsz = [300] sezts1z<-xase 
‘0 [300] sdureso<-xaso este 
/joyseuo [900] sdureso<-xase (ozts0) FF 
feztso = [390] seztso<-xase 
feztso + joyseuo =  yeodez 
} 
(T=>> ofods ‘T=>> eztsx ‘T =>> ezTso 
‘ (@ZT8I+EZTSO) =+Q0YsSeUO ‘--QD0 
£9 =< 900 /T-280839099°IPyA<-zAse = 300) TOF 


‘etdures<-xase = JOYseu0 


!g = ofods (oAod8j)3T 

‘setduestHjeedez* zpyn<-xase = ofods (oXkodsj) ZT 
Je ToADTHAeaseTdues "rpyA<-xAse ofods 
‘ge Tdures THAeedex * IpyA<-xAse eztsz 
J se Tdures THAOYSeEUO * IPYA<-xAso ezZTsO 
} 

(x02x0j) FF 

!((zozze’,u\pTs% = zozze - Apogspeol zeq3w :eTduespeoT,,) Snq)a 

‘(xase) ApogspeolT = z0zze 
{ 
740\. = ((6L‘ezts ; ds<-ds) NI] eueu<-xase 
!(ezts ds<-ds‘eqeq ds<-ds ‘oureu<-xase) Adourys 
= os } 

((aHWN aI ‘xAS8 GI ‘33+)dozaputa = ds)zt 

‘,0\,.=[0] eweu<-xaso 

/» Kae zy oureu Adoo x/ 

ie SzPU4y = (IPYUA<-xXACF) » 

i(eqeq ds<-ds) (x zepeeHge>toA) = zpyaA 

/* ewezZ OUT repeeygeston Adoo »/ 

‘((.U\GdHA eaegq :eTdurespeoT,,) cee 

este 

= { 

*XWEINAS WAAIII = TOTTSE 

‘(. i AQHA’ XAS8 ON,,) obessow 


a rs } 
(((aqHA aI‘xase aI‘33t)dozaputa = ds) i)3t 
2 ((n2\XAS8 SF 3x03QT05 pei mer ree te 
((WaOd AI‘XASS AI ‘FFF) SF3xXOQUOD) TF 
= } 
((40% WaIIII == rorze) || (D0d wagaaI == Torze) | | (z0TTEe;)) IT 


/((zozze’,U\pTs = zozrze - eTTzTeszed z9eyjze :eTduespeoT,,) 5nq)q 


4 (syqodo js * oyurlesreg<-xase 
‘SYYOROST TOS “ ogy uleszreg<-xaso 
‘syyodozd: oyuyeszeg<-xase 
‘xase GI ‘WaOd AI 


Ol a6eq a°XAS8ABId/XASB8ABid/Saae 


6 36ed 


*XAS89 (4 


(((awad aaar ‘oureueTTz ‘xase(y 


! (dOWAT_LINATTO) urznzez 
‘(40uua LNAI) wznqexz 


oyujeszeg 30onz48))eTTzTeszed = z0rz70 


{ (eweueTTz‘,,u\""* 8%, S5utpeey,) s3utad 


} 
ogujeszeg 3onz48))eTTyTUedo = r07r7e) j) FT 


((3F 7 OFULesreg<-xase=FZF) i) FF 
(xA80j) ZT 


/((.0\: eTdurespeot,,) 5nq) a 


{Jo = zozze SNOT 

{q00 UT 

fokods ‘eztsz ‘eztso SNOIN 
fqeedez, ‘joysouc, ALAG 
JzpyA,y TEpeEe_BgedtoA 

tds, Ajzedozgpez0yjs Aonz365 
33T* STPUEHAII Senay 


(eueUeTTS» SLAGN ‘XAse, OFUIXASIEST_ AONTAs) oTdurespeoT ONOT 


TARA EEA EEE EE EO 
(q*eszedzzt/setzrerqt{t) WAAIAI ue FO ssedons ToF O suINAeEY » 


“uoTQeSOTTeep Tox ezts 03 seqAqetdures<-xase but 33068 
‘eTdures<-xas® speOT/seRZeD0TTe pue ‘euweN pue IpPYA<-xASe UT STITH 


TIt3S ST STTF SUZ FT STTFTOESOTO TIts eTduespeotun “euop ueym 


()etduespeotuq ysnu 


()dozaputa ues noX os uedo eTpueHgdI SQ seAeET ‘oUTeUSTTZ pue 
‘OTPUEHAII OSN-uT-Oou YITM OFUIXASAYHSTA peztTeTatuT we ueatTS ‘xasg peew 


* 


-uedo 


nox °()sxunqoAdoo zo syxunyo TeucTaTppe 


RREK KKK KK 


* 


JE OUGO UU UUGOGUOOOOUUUUOOOUOOUOUUUUUUUEUUUUUEUEEEEEE. () STIUESPEOT xx/ 


/x ([T]ofe pue [o]ofe ueemjeq youtms »/ 


{ 
‘([ubezj] ote) uznqez 
{ 
fubez = bez 


‘0 : HIANWSXWN-8ZTS & (HTUNWSXWW < ©ZTS) = ezTs 


‘t= 
Jeum[oA= 
{potzed= 


/* OZFS Queurezrsep »/ 
‘ ([bez] ote) or3tem 


/« WTUZy 02 Asenbex snoyaerd oz ATM ¥/ 


/([ubez]ote(,3senbeyor 30n73s) )olutbeg 
seTokD_eot<-(ubezjote 
euNToA_| eot<-[ubezjote 
potzed_| | eot<-[ubezjote 


fezts : WIGNWSXWW é (@'IANYSXWN < 9zTs) = yQbueT_eoy<-[ubez]ote 


/zqdures= 
*IOANAd JOTAY= 
SaLIUM GWO= 


eqeq eot<-[ubez]ote 
sbeta_- oF ysonbexy_| | BoT<-[ubezjote 
pueumoy of -ysenbey eot<-[(ubez]ote 


/x T pue O BYDOTG OI eReUIEATe x/ ‘ty, bez = ubexz 


/x 2 {dures Jo esetd qxeu ey3 enenb x/ 
} 
(STGNYSXYN =+ IQdues 
‘0 < 8zTs 


!ST@NYSXUN - ©ZTSS = OZTS ‘TANWSXYW + IQdures=2Qdures) roz 


!T= 

JeumTOA= 
‘potzed= 

‘a TaNvsxvn= 
izqdures= 
‘Toauad JOTAv= 
SaLTIM dNO= 


/( [bez] ote (x 3senbeyor qonz3s) ) orutbeg 
seToky | ) Beot<- [bezjoze 

SUM TOA _| eot<- [bez]ote 

poftizeg_eot<- [bez] ote 

yqbueT_eot<- [bez]ote 

eyed | Pot<- [bez]orze 

sbera_- Oot* qsenbey_eot<- [bez] ore 
pueumog of ‘ysenbey eot<- [bezjote 

/x Sutketd w szt 3szTF SYR 3TeRS ¥/ 


o"XAS8ABId/XAS8AC|d/Sade 





: Source Code 519 


IFF Specification 


‘P at 
(x gzaq ‘([]asep auxa ‘ut ONOT ‘[]oeoznos gx) xOedUATA aLAG 


/* 

‘eqep ey ssexdmosep AT Teyzueue OUT OF seMTZ TeETEASE AT TIED » 
ueo noX og xX eENTeA eyep sAeT CYR suIN_eET AI “xX ENTeA » 

e3ep TepaTuy weaTh ‘zesznq ysep e3hq Uxz OWUT TETZNG 
eornos e3hiq u wors e3ep pepooue ejTep-TooeUcKTA yorduQ x/ 


{te‘et‘s8‘s‘e’Z'T’0'1t-'2-€-‘S-‘8-’ET-‘TZ-‘ye-} = [9T]BITSaOLEpOS ALAA 
/» ®3ep punos z0zx Huypooue eyrep fooeucdT” »/ 


/x sekeq eaejs Aq uoypsserduopep eyreq yooeuogt” --- o°yoedund x/ 


{ 
STTON = soqkqo tdures<-xaso 
{ 
/TION = eTdures<-xase 
! (seqhqoTduwes<-xase ‘otdues<-xase) wepeorg 
‘((.t\4pogs eezz 03 ynogy,,) nq) aq 
} 
(eo Tdures<-xase) JT 
} 
(xA80) 3F 
} 
(xase, OFUIXASIYST_ yonz3s) Apogspeotun pToa 
7A UU UU 
* 
eTdeus<-xase seqeooTTesg » 
* 
FAG OG OOOO BOOOOUOOOOUOUOBOOOUBUUUBUUUOUBURE nee ()APOETSPROTUN a¥/ 


{ 


/ (orzZe) urN_ET 
{ 
{ 
os { 
‘WENON WATIdI = T0OTTE 
/ (xase) otTduegpeotupn 
} 
esto 
{ 
!T >> seqkqs = se qXqetdues<-xase 
‘3 = eTdues<-xase 
!(seqiqs ‘eo tdures<-xaso) weyeerg 
$(q ‘seqXqs ‘eo tdures<-xase) yoedund 
/((,@\zezznq uotTssezduoDep eaey : Apogspeot,,) nq) a 
a } 
((aIHD GWEN ‘T>>s0e3hqs)weyooTIV(s» 3LAG) = ey 
/x “pepeeu zt ‘ssezduoceg ,/ (uotTssezduops<-xzpya) FF este 
{ 
/ (xase) etduespeotupn 
/((xozz0e 
‘,U\seqiq PTs peex ‘pty = zozz©e seqkgqyunyopeey :ApogspeotT,,) nq) q 
} 


(z0zze) FT 


‘quad wigadI = zozz0 
(seqhqs =; (se hqs ‘e tdures<-xase ‘zz7) soqAgyunyqopeey=ue TI) FT 
iseqiqs = seqiqetdues<-xase 
/((.t\zezznq peot eaey :Apogspeot,,) nq) 


Zt abeq I XASBACId/XASBAB|d/Saade 


} 
esto 
= { 
‘aOMAT BNAIIO = z0zz70 
} 
(((edAgureu ‘seqkqs)weympoTtTw(* FLAG) = eTdures<-xase) j) FT 


/ ((uopssezduops<-azpya ‘seqiqs 
‘,U\PTS=suoTsserduoo ‘prTgy=seqAqetdues :Apogspeot,,) 5nq)a 


!aIHO SWEN : OITdnd SWEW 2 uoTssezdmops<-zpya = edAqweu 
/» wou oTTGnd ojUT 3F peoT asnf s,3eT ‘sserduiocep oj eAeY OM FT x/ 


/ ((FFF) AURYDQueTAND) seqAgezopAuNYD = seqziqs 


= { 

‘(Qua wWigaaI) uznqez 

‘(nixXao@ 7 Qou :Apogspeot,,) ebesseu 

a ia } 
(((xao@ dI’xaSs GI ‘3FT) StTHUNYOQUETIND) j) FF 


(xa80j) 37 


! (Gowaa_INALITO) uznjzez 
((FFF" OFUTSSTeg<-xXASO=Z3T) i) FT 


! (40WsT TNALITIO) uznqez 
‘((,.4\: Apogspeot,,) nq) a 


‘Ax FLAG 
/IPYA<-xXASe9 = IPYA, TEPeSHRESOTOA 
fedXqueu SNOTO 
{Jo = xozze ‘ueTz ‘se jkqs SNOT 
‘J3T* STPUCHAIL ae 
(Xasey OFUIXASIYSTE AOnzAs) ApogspeoT ONOT 
DERM OEOE OORORROE OR EORR AR 
* 
“Wwa OQUT AGOd eTdures xXASE & PESY x 
* 
JEU U GOB OUUUOR UU SUUUUUUUUUUUUUUUEUUEEEeee: ()KPOESPEOT 44/ 


{ 
/(zase(y OFUTOSTeZ AONTAS)) OTTFTESOTO 
/ (xase) Apogspeotun 
} 
Pees 
(xase, OFUIXASIYST_ JonzT4s) oTduespeotTun pToa 
TRAKTOR REE OE UE OE EE ROR 
* 
()etduespeoy Aq p,ooTTe/peuedo buyyyArene seso[To pue seery » 
* 
JEG OUUGOOUUOUUUOUUOOUUUBOUU UE EEeeeneeee ()OTUSPEOTUN x¥/ 


{ 
/ (xozze) uznqez 
{ 
/ (xase) eTduespeotun 
{(xase(, OsUTesTeg AONTAS) ) OTTFTSEsoOTO 
} 
(x02) FT 


{ 


LL a6eq 


a XASBAPId/XAS8AB|d/Saae 





vices 


: De 


520 ROM Kernel Reference Manual 








/* WHII peaes zoz epow pue ‘qybzey ‘qapTm ebed x/ 


[sg] abze) toze 
[p]abze) yoqe = qybtey 
fe] abze) toze qapta 
‘(zjaize = eweuwqTt 
{(t]a6ze = oeweumex 
} 

/* SUTT pueuMIOD ETA souleueTTZ pessed «/ (SOUWNIN==06z2e) 5+ 


qadep 


2 (NEYM NUOLMI' (WANON WIAAIT) 770gaT) 0Xq 
((() daIOOTIW = FFF OFUTOSTE™“UqTT) i) FT 








/ (RaWM NUOLAA’U\AzezqyT eszedzzq uedo 3,ueD,,) oAq 
(((o’, 4zezqzT*oszedzzt,,) Axrerqyruedo = esegqeszedgil) i) FF 


{(NaWM NMoLTE’,w\"AzezqyT sotydezb6 uedo 3,ueD,,) ohq 
(((o’,Arezqzt* sopqdesb,,) Azexqpruedg = esegzsD) i) FT 


‘(nim NMOL’, u\"AzrezqyT wopypnquy uedo 3,uUeD,,) Aq 
(((o ‘nAzezqtt* uvoFapnquty,,) Axerqypiuedg = esequoTATNzUr) j) FT 


faSTwd : ‘aouL & (o==0b7e) = amMmozz 





im 3Ut 

Joureuuq{ Ty ‘SUeUMeZ, xzeyo 

feztstd NOTA 

fexqjxe ‘epoud ‘aybteqd ‘yaptad ‘yqdep ‘aubrey ‘qapT™ TuoHso 
fueTz ‘eTTFMer ‘TO = z0rzTe SNOT 


} 
(abzey, TeEYDd ‘OHxre Aut) upewU pToa 


‘amuiorz TOOE 


‘ [DMNIOTOONVXWN] ETIeIAOTOO §=6—LNOHSA 





{0} = WATT OFUINATI QOnTAS 
/TTON = esegeszegaaiIx AzrexrqTI Aonz38 

SUTTON = esegxy5, . AzezrqypT onz38 
'TION = eseguoyqynquix Azexq7pT qonz3s 








/(pyoa)dnueeto ptoa 
/(@ qut‘s, azxan)ehq pros 






eueumqTy eweumez WaTIOQMEY :ebesn, = ebesn, reyo 
9 SOUVNIN SUTFOPH 

‘ ,eTqegnqyzystpey ATeezg - WHTI O03 STTF MET sSzTEAUOD - G*LEA WATIOIWMEY, 
= qq6yxAdop, zeyo 
uS°LE WATIOQMEY :UAASO\n = STOAy TET 





‘yt\yqqdep aq6teq qapTa 





FTPus# 

/« Ayyeez x/ { ‘(0)urnqex } (pToa) jzoqexyD 3UT 
/» Suytpueq O/TaLo eofaaqer etqesta x/ { /(o)urnjez } (pToa)maExo 3UT 
AOLLIVI JOpr tH 





<4" YOueqyzom/youeqyrom> epntout# 
<Y OseqUOTATNQUT/UOFATNAUT>: epnTout# 


ut’ ddeuqrt/dzzt, epntout# 


/* 
SLTJOXEN COS - sOTNTpow eszedzzT Tereaes YATM ebexutT sezznbey » 

WEIL we oquy (MEYORWATI Wors) ETTF MET SRTEATOD » 
WATIOWED +/ 








Lebeg =" ING 7IOMeY/Wa TIO MeY/sade 


{ 
S([T]esanes ‘ysep ‘z-u ‘z+enrnos) yoedunta 
} 


{a SNOT 
‘[]lasep ‘[Jeoznos aLAzg 


(qsep ’u ‘eoznos) yoedund Pp 


*setdures pepoosue 3Tq-p 

(Z-t) xz Butstaduop seyiq z-u Aq pemoT{os ‘entea 
Tetatuy atq-g ue ‘e_Xq ped e sey zezznq eornos 
*zezgnq ysep eqhq (Z-u)¥Z O7UF TezZFNq SdINOS 
‘eqkiq u worz e3ep pepooue eyTep-TooeucgT” yoredun 


2%) esas 

/» eTdues o3fq T & ez0\s ‘x = [tT] i 
/x ®3T°9p pepooep eYyy UT ppe ‘[p]leatedoLepos =+ x 

/« STaqQFu ySTY eyQ 306 07 ATTUS iy =<< p 
esto 

/* ©TAQFU MoT SYR Jeb OF YsEUT ‘3X0 =3 P 
/* ©TGUGFU YSTY TO MOT QoeTOS (tT 3 t) 3T 
/*x seTqqtu zo zted e 3706 S(t << Fjeornes = p 
/* ®TAQtU MoT wey eTQqTu qSTY ‘eTQqTU Beep e epoDed * 


(F444 SUFT > F fO=F) TOF 
{fT >> U = WIT 


‘WET ’F SNOT 


€} abed o"XAS8ABId/XAS8AB|d/Ssade 


OA 


/* 
* 
* 
* 
* 


+/ 





: Source Code 521 


ion 


ificat 


IFF Spec 


{ 

/ (esegqeszegaar) AzezqyTesoTo (esegeszeggiI) st 
/ (esequotafnqur) AzerqyTesoTo (esequoT{TN{uL) IT 
£ (esegxzy) AzezqTTesoTo (esegxXs5d) FT 


(FFF OFUTSSIeT WATT) FF 


i (zzFF OFUTSSITeg “UqQTT) AATSCOCTA ; 


()dnueeto ptoa 


{ 
2 (8) axe 
/() duueeto 
{ 
£(,U\, =i () teqoQ0b) ettya 
+ (,U\LIXG OL NEnLAa Seen) I TT 
/» sebessou peer ued zesn Of ATEM »/ ( (84) 33 (amumoxzy)) FT 
‘(8 /,U\s%,,) 330tad RaeXsoe) se 


(@ qut‘s,» aLxzan)eXq pros 


= { 
‘(40 NUNLM 1) eAq esto 
= { 
!(TIWa NaotmE ‘un 1.) e%q 
! ( (zoxze) zz0g aT ‘,,U\8%,,) FRAT Id 
} 
(zozze) FF 


/ (@TTFMEZ) OBOTD 


{ 


€ a6ed oN 110Mey/Wg T110}“MeYy/Sace 


u\suotsueutp yoeyo - eTTy mez Hutpeot z0727g,,) y3uyad 


1((z >> eza3xe) + (dewata onzqs)zoezts ‘deuqyqzq-uqTT) weyeerZ 
{ 
‘ (qubyey ‘yapts ‘ [x] soueta<-dewatqaq‘wqTt) ze4seyoor gs 
ei Rade at 
(+44 /yadep>yx /o=%) TOF 


{ 
+ (eureuuqT Ft 
/x S3STT YUNYD TeuCTITPPe x/ “TION ‘TION 
/* xoToosuez “Butyyseu »/ ‘9 ‘SUONYsU 
/* SXOTOD »/ ‘y ‘ (OMMIOTOONYXEN ‘UQdep>>T) NIN ‘ETISITOTOO 
‘aybteyd ‘yaptad ‘quybtey ‘yqpTm 

‘epoud ‘deuqrqrq’uq ty ‘wqTts)uqTteaes = rorze 

} 

esto 
t 
/(,u\seuetd BbuypqesoTte z0z7g,,) squtad este 


(o => ee. 
((o=>ueTz) | | (z0rTe) ) TF 


! ( (T>> (DRAAOTOONVXWN ‘Yadep>>T) NIN) ‘OTAEQTOTOO ‘eT TFMeI) pesy=ueTI 


((o < weTtz) 93 (r0770;) ) FF 
/* 2TQBQTOTOD 206 x/ 


{ 
{ 
2 (eztstd’ [4] soueTa<-dew3tqzrq-wqTt ‘eTTsMer) peoy = ueTI 
/« euetd & peey x/ 
‘(0 (aubrey ‘yaptm) aZIsswa ASESSso gene ey ee 
& (zozze j) 37 
‘WHWON WAFAII = Torze 
(( (auS ey ‘yapTe) ze3SseYooTTY = ALS arte eer ete 
(+44 /(0< ueTz) 99 (zozz0;) 33 yYadep>y ‘/T=ueTI ‘Q=T0zIEe ‘O=%) TOF 
/ (aubrey ‘yap ta ‘yqdep ‘dewytqzq-wqTt) dewataatur 


=’ } 
(CaWaTo Awan 
‘(z>>ezqxe) + (dewata yonzys) zoozts)wepPoTTy = dew3ztqrq-uqtt) st 
fo : @ - yadep 2 8 < yadep = 


seuetd pue dewjtd eqeooTtIw « 
a/ 


{ 
!(aeM NUALTa' .) eAq 
/ (eweumez’,u\,8%, OTTZ mer uedo 3,uUeD,,) FqUTIAd 
} 
(((TIgaTO FAO oureumez)uedo = ET TFMEI) i) FT 


5 { 
1 (oO NWALTA’ t\,,) Aq 
/ (ebesn ‘qyubzakdoo ‘,,u\szu\sy,,) Faupazd 
} 
esto 
{ 
/(aqbyey‘yaptm) azisswa = eztsTd 


10: FOWI é oop =< aybteyd =| epoud 
10: SHHIH é O09 =< YapTad epoud 


00z é 00z > aybtey = qubteud 


‘qybtey é 
OzE 2 OZE > YIPTA yaptad 


SWapTa 


O° W710 MeY/Wg 110MeY/Sade 





vices 


De 


522 ROM Kernel Reference Manual. 


wAzezqtT “wos qyngut,,) AzezqyTuedo 


osequot{tnqur) i) FT 


FOUL (o==06ze) = qmwoxzs 


fy /T 3Ut 
feureueTTI zeyo 


‘yoo Tbes ‘Jo = xozze SNOT 


/*« ®ZTS YOeRIAS 

/* MOPUTM TOOL 

/* exnAONzAS TEemezG 
/* K ywerzMND 

/* X ywezmMD 

/s Kezxzy edky Too, 
/* TOOL 3Tnezed 

/» edKy, wool 


/* &3eq resp 

/* QI 36peo 

/x OFUI TeToeds 
/* Opntoxg” Ten30W 
/x 3%eL 3e5peo 

/» ebeur AoeTes 


/» ebeur xepuey »/ 


/» edky ebpes 
/« sbeTg woTqeatqoy »/ 
/x sbeta x/ 
/= yaSteHn ‘Yaptm ‘dog ‘aseT 
/* xequtog yebpep 4xeN 
/x ernqzonz3s yebpey peppequa 
/x UOTSIMA 
/* zequay oTbew 


/» ebeuy 3xeNn 

/* FFOUCeURTA ‘HOTGeuetd 
/+_23ep ebeuy 

/*« 7deq ‘3qSteH ‘TaPTM 
/» xeuzoD azeT z0eddg 


Sueezogquozlg, weexog WoNnz485 


} 
(abzeyy TeYo ‘oHze Aut) uTeU pToa 


“TION 

— “TION 
‘NOILISOd_NOOI_ON 
‘NOILISOd NOOI ON 
‘STOOINGTI 

‘ Aetdsta, 


‘TINGTILS (ALY) 
«/ ‘LISAYD' TOO 
‘ALWVIGANNISGWS | AITMAATAU 
‘T71aiowaoawS | JSYWISGYD 
»/ ‘wz ‘v9 ‘0 ‘0 
x/ “TION 
x/ sot 
«/ ‘NOISUZANSIG_dM 
»/ ‘OISWOISIG aM ; 
= qoefqowaTI yefqoysta 3onzAs 


‘ PAMTI=AdALITIGn 
} 
= []STOOLNaTIIy ALAGO 


#{ 
TION 
‘0000x0 ‘€000x0 
‘eqeqTINaTI 
‘e ‘€z ‘v9 
‘o ‘o 
} 
= TIWaTI efewy jonz48 


‘00000 ‘00000 ‘00000 ‘0008x0 


“¥SSSx0 ‘'SSGSxX0 ‘SSSSX0 ‘SSSax0 ’ F000=0 ‘00000 ‘00000 ‘000dz0 
"YOaExXO ' IAIXO ‘ ILTIXO ‘DAEATXO ‘ POEOXO ‘0000X0 ‘00000 ‘0DEaxO 
“¥D00X0 ‘GESSxX0 ‘SLA0X0 ‘O00EAXO ‘PD00X0 ’.2ZDD0 ‘0000X0 ‘O0EdxO 
"¥OTOX0 '99DDxX0 ‘00000 ‘0800x0 ‘F6TOXO ‘Z000X0 ‘00000 ‘osTax0 
“¥6TOXO ‘00000 ‘0000%0 ‘08 TAX0 ‘PE TOX0 ‘0Z00<0 ‘Z000X0 ‘OsTdx0 
“¥6TOXO ‘0D00X0 ‘78.49X0 ‘O8TAX0 ‘F6TOXO ‘OBTOXO ‘78.4ax0 ‘TSTAXO 
“¥6TOXO ‘OOLPXO ‘08A0x0 ‘ TSTAX0 ‘PETOXO ‘00RIxX0 ‘ESBAxX0 ‘OBTAXO 


z a6eY 


2 O@APGUSOINS/eAPGUdEINS/Sdde 


“¥OTOXO ‘000.80 ‘TOLOX0 ‘08040 ‘PD00x0 ‘0004x0 ‘ TSE0xX0 ‘00EaXxO 
‘92000 ‘0084X0 ‘00TOX0 ‘00Edx0 ‘ FOE0X0 ‘0000X0 ‘00000 ‘oDEazO 
‘VOAEXO ‘ dAIAXO ‘ ITIIXO ‘D.IEAXO ‘¥O00X0 ‘0000X0 ‘0000X0 ‘000ax0 
“PSSSX0 ’SSSSX0 'SSSSX0 ‘SGSaxO ‘EadaxXO ‘TATIXO ' IAIIXO ' IIAIXO 

/x T 9UeTa x/ 
* PAAANO | ATAARO ' AATARO ' ALALEO 
“€000X0 ‘00000 ‘00000 ‘0000X0 ‘E444X0 ‘ FF49XO ‘ IALIXO ‘ 1AL0XO 
‘€.a44X0 ‘0000X0 ‘0000X0 ‘F440X0 ‘E.FIEXO ‘0000X0 ‘0000X0 ‘D.4.40X0 
“€4L0X0 ‘CETHXO ‘BLAOXO ‘OALOXO ‘EATOXO ‘.1Z700XO ‘OAOTXO ‘08.400 
‘€40DX0 ‘AV00X0 ‘OFOTXO ‘00400 ‘€900X0 ‘TTAAX0 ‘EADTXO ‘0090X0 
“€900X0 ‘OZHAXO ‘ TOATXO ’0090X0 ‘€900X0 ‘OP AAXO ‘ TOATXO ‘0090X0 
*€900X0 ‘000.4%0 ‘00000 ‘0090X0 ‘€900X0 ‘000.4X0 ‘T000X0 ‘0090x0 
“€900X0 ‘0008X0 ‘E0000 ‘00900 ’€900X0 ‘0090X0 ‘0000X0 ‘0090x0 
“€400%0 ‘00980 ‘T000X0 ‘00.40X0 ‘EATOXO ‘00D8X0 ‘ TODTXO ‘08.100 
*€ALOX0 ‘0082X0 ‘08S0X0 ’0F0X0 ‘EATEXO ‘0000X0 ‘0000X0 ‘D.a40X0 
*€d41X0 ‘0000%0 ‘0000X0 ‘ A440%0 ‘E44axX0 ‘ FA19XO ‘ 1ALAX0 ‘14400 
*€000X0 ‘0000%0 ‘00000 ‘00000 ‘T0000 ‘0000X0 ‘0000*0 ‘00000 

/* 0 SURTA - 

= []eqeaqtInNair oeonn 

” 


* 
WATI peaes xox woot qoeford zoz ejeq »x/ 


‘[ZsdoaNnr]Fnqu zeyo 
8ZT ZSANENI SUTFOPH 


feouenbes ‘uooron ‘AeTegon ‘3eTNd ‘qMWOTF TOO 
{0} = WqTT OFUINGTI JONTAs 


/TTON = osegeszeggarI, AzerqyT Aonz3s 
!TTON = esequoorly, AxerqypT yonz346 
‘TTON = osegxgso, AzexrqtT qonazys 
STTON = esequoTqtnqury AzexrqyT qonz45 


2 (pfoa)dnueeTo ptoa 
!(@ qut’s, anxan)eXq ptoa 
i(s_ zeyo) sqebAu ut 


/,U\" (AWIGGON sseTun) Kejep oes-o0T xeQysye ueeros QuOry senes, 
»U\ (eweu og zequmu e sppe eouenbes) ZONENOGS ‘NODION ‘AWTSCON ‘LEINS :suotado, 
nt\ (preoqdtT> zoz [3tun]o- ouweueTTz) eureueTTy eaesucerzos :ebesy, 
= ebesny, xeyo 
‘,eTqeanqTzystpeu ATeezz - sepow meu sqizoddns - g*.eEa eaesueezos, 
= qqbtaXkdopy zeyqo 
/uG°LE PABSUSETDS :URASO\, = STOEAy TEYD 


FTpue# 

/s Aytveez «/ { /(0)uzngez } (ptoa) yroqeyxyqo 3uy 

/»s Suytpuey O/TALD eot3zaqeT eTqesta «/ { ‘(0)urnqez } (ptoA) miaxD 3UT 
FOILLVI FOPs tH 


<y*soqord woot /qtTo> epntTout# 


<4" youeqyxrom/Yyoueqyzom> epnTouT# 
<Y°OSeCUOTATNAUT/UOFATNAUT> epnTouT#H 


vq ddeuqtt/dzzt,, epnTout# 


/* 

SLTFJOEXEN Seg - seETNTpou esredzyzt Tereaes yRTM ebexutT sextnbey » 
WHII ue se ueeros Quorzy sears » 
eaRgueezDs »/ 


| ebeg DBALPGUIBING/BAPGUZ9INS/Saae 





: Source Code 523 


IFF Specification 


{ 
(T) uznqez 
TION = Sx 
»)) eTTYM 


f4+T ‘++ ((xeu > T)39( .U\,=i (()zTeyoqeb = sy 


‘T - ZSANAGNI = xeu ‘9 = T a 
(sx zeyo) sqe6Au Qut 


{ 

/ (eseqoszegaar) ArerqyTesoTo (eseqeszeggal) Ft 
/ (asequooz) AzezqTTesotoD (@seguocl) FT 

/ (asequoyqzynqur) AzerqyTesoTo (@sequoTZTNAuL) FF 
/ (eseaxzo) AzezqpiIesoto (esegxs5) 3T 


‘(FFF OsUISSTeg “UqTT) AiTSET pads Aaa ery 
()dnueetTo ptoa 


{ 
1 (©) 3Fxe 
/()dnueetTo 
{ 
‘(Lol snquy) sqebAur 
?(.U\LIXE OL Neat ciaicicab Bese 
/» sehessou peex ued Jesn Of 4TeEM x/ ((84) 99 (@mMUOTZ)) FT 
‘(8/,.U\sg,.) squad ( (8%) aa813 
(@ qut‘s, gLxAGN)eAq pToa 


_ { 
$(4o NMATHA‘ wn) oXq 
S(ut\n) Fquzzd (qetndj) Ft este 
{ 
/(,u\peaes uooy,,)zFquTzd (3e;Nd{i) FT 
{ 
‘(NavM NYALTA’,,u\uooy Buyaes roz7g,,) 0hq 
} 
Aare ety Senne ene reactant ae 
/*= pzeoqdtT> jou «/ ((,9,=j [T] eweuel tz) 939 (,-,=) [0] eweueT Tz) 99 (WOOION]) ) IT 
/(eweueTTs’, """s% se peaes uee2os,,) sQuTaAd (3eTNdi) TT 
} 
este 
{ 
/ ((zozze) reg aI‘ .U\s¢,.) FQUTId 
} 


( (euweueT tz 


yebed I eAPGUdAIDS/eAeSUaEINS/sdde 


‘TION ‘TION 
‘usezosquory ‘Uq[T¥9)eaesuSseTDS = XOITS)FT 


*() tuted 
fueezDs4sata<- (eseqUOTATNQUL (x SSeqUOTATNAUL AoNIAS)) = uUseTOgQUOAZ 
!QOptqzrog 


‘ (00g) 4eTeq (APTSGON]) 5T 


{ 

{ 

‘To]lgnqus = oureueT tz 

} 
esto 

{ 

! (TIwa NYoLTa’,u\peztnbez sueueTty ‘peaes jouw Herene hens 
/*= 4TXH - ouweueTty ON x/ (O==T)3T 


‘(Lo]Fnqus) sqebAu = T 
(, !@aes ZOZF oweuelTty r0e4QugZ,,) Fautazd 
J (ebesn ‘qubtzkdoo ’,,u\sgu\sy,,) yQutrd 
} 
ests 
{ 
{ 
iynqu = suweueTty 
{ 
= fyeezq este 
 (yooTbes) yooTun ((aquaa ssdoow‘snqu) yor = yOoTbes) TT 
‘(4 oureueT Ts ‘..PTHOsSs$. ‘FnQu) FquTzds 
} 
(+44 /6666>% /T=%) r0Z 
} 
(aouenbes) JT 
{ 
eouenbes (((.3ONaNOgS. ‘ [4] abze) duotz3s) j) Ft este 
qoTAdD (((nLaTNS, ‘ (4) 4628) duptzys) j) FF este 
uUODION (((uNOoION,, ‘ [x] abze) duotz3s) {) FT este 
AeTOGoNn COG RETAGOH CURSE Sent ae es 
(+44 {(obze) > ¥ /Z=H) TOT 
‘asTwa = esuenbesg = AeTtnd = uoocron = AeTeqon 


{(t]abze = ouweue[Ttz este 
= { 
‘(do NanLME' t\,,.) Aq 
/ (ebesn ‘qubtazkdoo ‘,,u\sgu\sy,,) yQutsd 
} 
dseeton ir iacnet sy 


/= SUTT pueWUMIOD BTA oueUeTTZ pessed «/ (T<262e) st 


 (NaWM NUOLMI’ (WENON WAIsAT) 20741) Aq 
((Q)daIPOTTW = FFF OFUISSIEA“WqTT) i) FT 


/ (NaWM NnLTA’,.u\"AzrezqtT uooy uedo 3,ueD,,) eAq 
(((o/,Azezqtt*uoot,) Azezqtquedg = esequoor) i) FT 


‘(NaWM Nunigy’,u\*AzezqtT eszedgzt uedo 3,ue9,,) eAq 
(((o’,AzezqyT ‘eszedzzt,,) Azezrqtquedo = esegeszedaal) i) Ft 


/(NGWM NUngma’,u\Azezqtt sotyder6 uedo 3,ueD,,) oAq 
(((o/, Azezqty’ sotydez6,,) Azezqtquedo = esegxy5) i) FT 


S (NGM Nunima’.u\AzezqtT uotatngqut uedo 3,ueD,,) eq 


€abeg  DeACGUA0INDG/ANeGUaeINS/Sdde 





vices 


: De 


524 ROM Kernel Reference Manual 


} ( (€ < uydeq<-uq) 39 yoreaqQe) ZT 
{ 
‘(zpyop ‘o ‘eueu ‘dz ‘uq)eqtidsa 
1 (dz) aTao24 
Su/x rseuetd omy repro remot Hbututequoo eqtads--x/, ‘dy)squtazdz 
} (Tt < aadea<-uq) ZT 
2 (dz) aTaoza 
2 (smoy<-uq /y/% ------ PT$ = Y :3euroz eqTads -----x«/, ‘dz) FquTIds 


} 
(zpyop Tood ‘YyoeIIe TOOE 
‘oweuy GLAGN ‘d3x AITA ‘way dewata yonz4s)eqradsquyzg ptoa 


{ 

+ (dz) aTaoza 

(dz) aTao7a 
Daf ode) sQupazdz 

esto 
i(u/* eatads Jo pua x/ /{ 0000x0 ‘o000x0 . ‘dz)z3utzdz 

(peeyop) ca 
fuetdm =+ Tda 
fuetdm =+ odm 
+ (dz) aTaoza 
GRE SaTne 


2 n/a 


!([zotToo] sxotoo ds ‘,0%, ‘dz) zsqutzdz 
(Tt 3 ((F-ST) << Odme)) + (2 3 ((F-9T) << Tdmx)) = zoTOo 
} (+44 ‘97 > F 40 = F) xoOZ 
Ee Oey eA ep Sa 
I(n‘a ‘dz) squzazdz 
} ((T-smoy<-uq =; £) || peeyop) ZT 
‘(tdmy ‘odm, ‘uxposx0 ‘xvogxo . ‘dz)squyadz 
} (++ /smoy<-uq > € / o=f) eed 
1 (dz) aTaoza 
u dz) FQutzdz 
} (peeqop) xT 


i(u/x doqsa ‘azeasa »x/ ‘0000X0 ‘0000x0 


+ (dz) aTao7a 
‘(spzomu ‘oueu ‘,} = [PT$]s% qaomn. ‘dz)zquTa@dz 


‘[1+d] seueta<-wq(, moma) = Tdm 
/[d] seueta<-wq (x GYoMn) = oda 
2(O:PEPeeqop) + SMOY<-UdyZ = SprOMT 


!Z/mogzegsejAg<-wq = uetTda 
/* ZojToo Textd x/ {ZOTOD 
/» seTrezoduey reqUNOD »/ ‘spzomu ’£ ‘FT 
/x setTzexodueq reqUTOd »/ ‘tdm, ‘odmy 


qroys 


qaoys 
qaoma 

} 
(peeyop iood ‘d guy ‘eueuy gixdn ‘dyx FITa ‘wqy dewata qonz3s)eqtazdsa ptoa 


? (dz) araoza 
u dz) FQuprdz 
{ 


aaa eS 
2(u/*e nv ‘GZ) ZF Qutadz 
(03 ((F-ST) << (qu+dam) ») )) 


o-O}uNdWq/Sejnpow 


“y2%,. dz) squtazdz 
(447 S9T>T / O=T) xOF 
(+4qu /T << (moyzegse zAg<-uq) > qu ‘oO = qu) xroz 
Sn a/Wn dE) FQatazdz 
} (9 => moyzegseqAg<-uq) FT 
1 ((qutdm)» /u/xp0sx0On ‘d3)zqutTzadz 
(+4+qu /T << (moyzeaseqAg<-uq) > qu ‘9 = qu) rox 
t(n ow “E5) FQUTAdzZ 
} ((T << mogzegse3Ag<-uq) =+ dm ‘++€ ‘smoy<-uq > € ‘9 = £) zoz 
‘ (dz) aTaoza 


i(spzomu ‘(, ,:(d+,0,)ed) ‘oueu ‘, } = [pT$]>¢s% quomn. ‘dz)z3utazdz 
(dz) aTaoza 

IPTS # oueTd ‘dg) zqutadz 

‘(d] soueta<-uq(, qgomn) = du 

/« euetTd atq yore tog x/ } (d++ ‘qqdeq<-uq > d ‘9 = d) xoz 

1 (dz) aTao za 


2 (smoy<-uq ‘g,xmoyregseqAg<-uq 
=U ‘PTZ =H? a/y ‘dx) FQutzdz 


i smoy<-uq, (7/Moyzegse qAg<-uq) = spzomu 
/x» setzezodure  »/ fqu/C ‘td 


qroys 
qxroys 


/x eyep deuytq ey3 09 TeRUTOd «/ idm, qaoma zeqstTbexz 
} 
(eweu, BLAGO ‘dyx FIA ‘wqy dewjta 3onz4s) qoq qutid pToA 


{ 
2(ut\n ’d5) sQutadz 
este 
Smo ‘axo 1.330%, ‘dz) FQuTIdz 
(aTIOOP) ST 
} 
(dyx AIIA) dTIOTa PToa 


/4900°,, = []szoToo ds zeyo 
!aTaD0p Tood OF7eAS 


‘(zpyop TIood ‘yore 3e Tood 
‘oureuy SEAGO ‘dy, ATIG ‘wqy dewata yonzys) eqrzdsjutig proa 
‘(eweuy BLAGN ‘dye TTIG ‘wqy dewata 3onz4s) qogzutIzd pToa 
‘(dy WII) ITId7aq PToa 
/(peeyop ood ‘d juz ‘oureuy anxan ‘dye ATIa ‘wq, dewata qonzys)eqtadsad ptoa 


T SAX SuTzep# 
O ON eUTzePpH 


<YOTpys> epnTout# 
ut ddeuqtt/dzst, epnTout# 


s@[npow eszedszzt yQTM osn ros WAD Aq 16/G0 PETFTPOW 
eset Suny ‘stuewow yOnyD Aq 3Tq & peTzFtTpou pue dn peuesto 
*zeqnduos ebtuy-eropoumop eyR TOF uoTSIeEA sTYUL 


‘ufeuop oTTqnd ey ut st eTeMAyTos sTUL 
“sqzw ofuozQ0eT” ‘meys eaeqg pue uostazom Azzec xq 


deuytq xoz ejep Fo uot Requesezdez efenbuet-p e yno jutad 


p°aqutazduq 


o°O}UNdUWIG/Sejnpow 





: Source Code 525 


IFF Specification 


fezts ds<-ds = ezts yo<-yunyo 

= _ } 
((edXqueu‘ezts ds<-ds)wewooltty = eyed yo<-HUNYS) FT 
(t+) syqodord = aI_yo<-xunygo 
{[y] sxqodozd = edAy yo<-yunyo 


} 
(Q4Wa1IO aNWaN| odxqueu’ (yung 2Onr348) Joez Ts) We_OOTTY 
(x yUNYD JonTAs) =yuNYS) FT 


£((CLt+4] syqodozdy ‘ (4) syqodozdy’,,u\yunygo spy's°sp's Pasha DG 
(({t+4] syqodord ‘ [x] syxyodord ’z3 +) dozaputa=ds) FF 
= ) 
(z=+4 ‘(Nod OWL =i [4%] syqodozd) 339 (syqodozd) 99 (zozzej) ‘o=%) z0F 
‘9 = z0zze 
/* syunyo Ayjzedoxzd pezeyyeb Adod y/ 
(TIAN) urnqex (F3TIDFF 
f4q Of ‘4 QUT 
{zxozze Buot 
{FTOx /FOx WERLUOFAOSTTOD Jonz36 
‘ds, Aqzedozgpez0js AonzA45 
STION = yanyoaerd, ‘TION=352T3% ‘yuNYO, YUNYD Qonz345 
} 
(edXqurew ONOTO 
‘SAYDROSETTODs ONOT ‘sxyodord, SNOT 


‘33s STPUCHAAI QONTAS) syunyoAdoo, yunYyD Aonz3s 
/» 


@INTTeF TOF O suznqjey 


“STTZ O42 UT Ptp AeqQA se AstTT Yunyo ut 
UydUO ANWS ut azeedde AeyqA os syuNYS UOTADeTTOS sxrepr0EeYy 


* () as Pryungpjeez 3 
buttres Aq syxunyo petdod Fo astT eyQ eezyZ TEAST Asnu noZ 


*syunyopetdosozujeszed ut zequtod sty3 ezoqs prnom nok AtTezeuesy 
“3Q8TT ©49 FO QTEQS EYQ OF AZEQUTOd e surnqeI pue 

‘sezrnqonazys yunyD FO 3AstT pexutt AtHuts e oL 

eTpuegaarl peszed-Apeorzrte ue Woud 
SYAYOROSTToOo pue syxyodord ut petsztoeds syunyo setdop 


() squnqoAdoo 


Ee R KKK KKK KKK KKK K 


/ 


/yeexzrq 
‘(zpHop ‘yoegqqe ‘oureu ‘dz ‘uq)eqtrds3utzd 
?ULIwds eseo 
/yeerq 
‘(eueu ‘dz ‘uq) qogqutza 
:@od eseo 
} ieee ease 
iyeerq 
‘saxX = aTaop 
24P, 
/yeerq 
‘ON = IPHOP 
:,U, 
iyeezq 
‘sax = yorgqe 
‘airaas = edxy 
2,8, 
/yeezq 
‘ON = youd qe 
‘g~Tads = edXq 
2,8, 
/yeerq 
‘qoa = edXq 
2,qQ, eseo 
} (2) youtas 
C0 =i (+4+9034=0) ) STTUM 
7ON = Yoregqe 
‘goa = edkQ 
‘sax = IpHOP 
‘ON = aTIOOPp 


tedX3 LYOHS 
io zeyo 


Devices 


wT FFF/dITT. OPRTOUTH 
‘zpHop ‘yoeq qe TooE 


} 
(quy~ GLAGN ‘ouweu, aizdo ‘dyy FIG ‘wq, dewata jonz3s)deyoqutzawa ptoa 
/* 
“"WHII SYR FO uoT_eQuesezdez 5 sqndqno ‘(moTeq sesed ees) peTTsep AeUTOF » 
and3no ey3 Butqtzosep Bbuyzys pue ‘eTTF YATM peyzeToosse oureu , 
‘e3yIM XOZ pouedo eTpueyeTTs Oo ‘ernqonzA3s dewjta og zequTod pesseg » 
deyoqutiand +/ 


~ 
* 


“sWuod eTduyps z0z 
Aluo eTqeayns sft pue WeTF sy uoyyequewetduy sty 3eqR EI0N 


“weqy eqeD0TTeep oj ‘Apeexz ueym ‘() 38st TXUNGOeerZ YAM syXUNYo 
petdos eyQ eezy 03 zequeuwez ’()sxunqoAdoo pesn eaey nod Zr 


* ()3sTTXUNYDSITIM YITA ETPUEY Mo e 02 Ano yor 


UGAAITAM puUue peTF {pow eq ued sXUNYS FO AsTT pezeexro SUL T LrTuds eutzep# 


0 aod SUTyepH 
(suezbozrd xeyj0o x0 gzTes Aq eyTIM XO peex oz peuedoex eq o7 

03 pzeoqdt{TS zo eTtz BHbuymotte) BHbutszed zeqze AyHtz pesoto { 
eq Aeu eTpueyq azar 3eGR O8 QxOEQUOD FZ} Ue Wor 


sxuNYS uwoT_AoeTToD pue Aqzredozd pezeyqeb znoXk setdop 
“syunyo pezeyqeb eouezesez TTT3sS 3Nq STTS AAI SYR SSOTO OF 
peeu jeqQ suerbord zey30 pue suexbord eytim/AZTPOW/peey r0g 


syunyqoAdoa 


o°syunyokdoo/sainpoul 


RRR KKK KEK KKK KEK KK KK 


i(zpyop ‘z ‘euweu ‘dz ‘uq)eqtizdsa 
! (dz) aTao2a 


:seuetTd omy repro zeybty buyupequoo eytzds--«/, ‘dz)z3utzdz 
S(uTn ‘oued) Qe0zQ45 


o9}ULAWIG/SejNnpow 


Su/as 





526 ROM Kernel Reference Manual. 


{ 
/ (asatz) uzrnqex 
{ 
/ (z0zze) uznyAexz { 
2 { ITION = 38213 
# ((xozz0 /O2F8 aI yo<-yunyos ‘(qsztz) astTAunyooezz (3SITZ) FT 
+, U\PTZ=TZOTIS ‘PTe=eZTS sys and : Ast TyxunyoogTIM,,) hnq)a } 
i(egeq yo<-yunygo ‘ezts_‘dI yqo<-yungo ‘J3t) NOAA = AOAIS (20220) FT 
fezts yo<-yunyo =: (e3ed  Yo<-yUNYGD) ueTI345 
é (NMONINA BZISddI == eZTS yo<-yuNGo) = ns { 
(Qx0N Yo<-yunyo=yunYyS {(zoz7e;) 33 YUnYoD /AsrTF=yuNYo) r0z { 
ta z0zz9 esTS 
£((aszyz',.U\x1s$ = zequTod yungo yeztzZ 23st TXUNYOeQTIzM,,) fnq)a ‘ { 


‘0 = zozze ‘ezts Buort 
fyunygo, yUNYD AonzAs 
} 


(3s2zTF*e YUNYD AONTAS ‘FFTy STPUEHAAI FORTIS) QsFTAUNYoeRTzIm Huot 
/* 


WAIIII we TO ssedons oJ O suINIeYy 


9zys se erey pesn_eq TITM 
(eQeq Yo<-yUNYS) UeTIAs pue eTZS YO eq4R Se NMONINO FZISdII 
esn Aew nok ‘Huy~r4s peqeuywxzeR [Tnu e& st eAep JI 
s,AUNYD QONTAS FO ASTFT 3NO SQTIM -— YSTFTYUNYOoRTIM 


i] = zozze 
!TTON=yunyo 
i((yquny9 3onzQs) Joezts ‘yunyo) weyeez7 
} 
este 
{ 
fyaunyo = yunyoae:rd 
dyunyo = 3saTz esto 
_‘unyd = 3xeN [ yo<-yunqoaerd_ (qunyoaezd) st 
J (eztg Jo<-Tto‘eqQeq | yo<-yunyo ‘eqeq TO<-}FTo) weyAdoo 
fezts TO<-TTO = ezTs “qo<-yunyo 


IFF Specification: Source Code 527 


7 
((edAqureu‘ezts TO<-TTO)WeWPOTTY = B3eq Yo<-HUNYS) TT 
{ ![T+4] syyoqoeTToo = —_aT_yo<-xunyo 
! (TION) uznjez ‘[y] syqoqoettoo = edAy yo<-yunyo 
{ } 
‘(yunqo) uzngez ((pT == aI yo<-yunyo) 39 (edAq == edAy yo<-yunyo) ) FF ((averI1D aWaN|edXqureu’ (yunys 3onrT3s) JoezTs) We_ADOTTW 
= } (, yUNYD 3ONrIAs) =yuUNYS) FT 
(qxeN Yo<-yUNYo=yuNnYoO /yunYoD /AsxrtF=HuNyYo) roF 
/((44/.U\PTS zequmu buykdoo _,,)5nq)q 
iyunyqo, yUnYD Qonaz45 a 
} IQXON FO<C-TEO=TFO (+44 /AQ>AY /FOHTTO ‘T=AA) TOF 
(pt Buoy ‘edAq Huot ‘Aszzsx AuUNYO AourAs)XuUNYyOpuTsy YuUnyO Jonz3s } 
/* (--"q fuq fxq ) Z0z 
punogz euou FST TION XO ‘y» HUNYD QoNzAAS surN}eT » 
= a * /((F2/AaA’U\XTS$ 3 ST AsaTz ‘oseyy FO pT% ere oreyL ..) 5nq)a 
/(QNUD AI’WETI aI ‘sxunyopetdoo<-td) yunqoutz eTdurexe * _ 
syunyo 3OnTAs FO ASTT ut yunyo Hutyo em ysrty putz - yuNyoputy »/ P4449 (AXON TO<-TTO=TFTO {TPO fO=Aq ‘TO=TTO) TOF 
T+H] SYYDRDOT TOO ‘ [4] SYYOROSTTONZ ’,,U\UOT_DeTTOD sp°y"sp"% HutAdoo,,) hnq)a 
} 
{ (({t+4] sxyDqoeTTODo ’ [4] SYYOIDET TOS ‘FF T) UOTIOOTTOOPUTA=TO) FT 
7qxeu = yunyo a } 
CQqang qonzy4s)jJoezts ‘yunyo) weyecers (z=+4% /(3NOd SVL =i [xX] SYYOQO@ETTOO) 33 (SXYDBDSTTOD) 399 (TOTTe;) /OQ=y%) OT 
. (az ts  yo<-yunyD ‘ eqegd [ yo<-yunYo) WeNees 7d /x* Zepzro esxeEAeT UF sYyuUNYoS uofpAoe>[ Too pezeyqeb &doo «/ 
((NMONOING aZIsddI =i ©zts yo<-yungo) 99 (eaed | yo<-yunYyD) ) FF 
/qxen [ yo<-yunyo = 3xeu { { 
} 
(yUNYS) eTTYA !] = rozze este 
/qsaty = yunyo { 
{ 
sqxou, ‘yunyo, YUNGD QonazAs ‘] = zxoxzze 
} ?TION=yunYyoS 
(QsztFx YUNYD AonTAs) QeTTHuNyoseezzy PToa ?( (yung ARRAS ORE een ee 
/* 
pe zesoTTesp eq 30uU [TT * esto 
eQeq YO Sat ‘NMONDINN Y aZISGII ST OZTS YO s,YUNYO & FT - SION x» { 
* syunyo = yunyoaerd 
* eqeq yo sat so [Te % zyunyo = 4satz esto 
pue ASTT wyunyd pe yecoTtTe Atteotweukp eS ser - AstTyuNnyooezsy / : syunyo = 3XON [ yD<-: —yunyoae:rd (qunyoae2d) 3st 
!(eztg ds<-ds ‘eqeq yo<-yunyo ‘eqeq 1 ds<-ds) weykdop 


do9/seinpow 


“syunyoAdoo/sejnpow 





‘TION = dew 3tqzq<-wqTt 
2((Z >> ezaxe) + (dewata qonz3s) yoezts ‘dew tqaq<-uq Tt) weyeer7, 
8 - y3deq<-dew3tqzq<-waTt ¢ 8 < yydeq<-dewytqrq<-uqTt = ez3x0 


{ 
! (smoy<-dew3tqzq<-wqTt 
‘(€ >> moyzegsezig<-deuwyqtqzq<-wqTt) (LYOHSN) 

‘ [x] soueTa<-dew3 tqzq<-wqT Tt) reqseyoor gs 
( [x] seuet g<-deuytqrq<-wqT Tt) sF 
} 
(+44 /yqdeq<-deuqtqzgq<-uqrTt >x ee 
(dew tqiaq<-wqTt) 3F 


fo=ezqxe ‘AY RUT 
} 
(UqTT ¥ OFUINGII 3OnIX4s)deumqtqeezy ptoa 
/* 
seuetd pue eznjonzyjs dewqta deuwatqrq<-uq{T}~ seqeosoTTeep » 


* 
deuytqeery x/ 


{ 
/ (z0zze) UINAE= 
‘I = zozze este 
{ 
{ 
/ (uq Tt) dew tqeezz 
£(,U\zegsez eAedoTTe 03 peTTeyg,,) ebessoeu 


} 
(zr0z28) FT 


{ 
‘(0 (a6ty ‘opta) azisswa ‘ [4] seueta<-deuytqzq<-wqTt) 2eeTOITa 
(z0ozze j,)3T 
‘I = zozze 
(((q6tq‘epta) zeAseyoottTy = [x] seueTa<-dew3tqzq<-wqTF) j a 
(+44 /(z0zz0;) 33 deep>y /o=y%) r0z 
! (q6ty ‘opta ‘deop ‘deuytqzq<-wqTt) Sosa 
((awato aWaW’ (z>>e23z0)+ (deyata 30nz3s) JoezTs) we_POTTY = deuryjtqzrq<-wqTT) FF 
‘0 : g - deep & g < deep = exzqxe 
/* 
seuetd pue deuw3jtd S3e0°0TIW x 
+/ 
 ( (deep ‘ySty ‘opt ‘pywq 
‘,U\PT3=deep prz=45ty PTR=OpTM xTe$=pyuq :deuytqooTTe,,) Snq)q 


‘ (aqT Tt) Bureoqe6 = Bureo<-wq Tt 

/seueTqu<-pyuq = deep 

fy<-pyuq = ybty 

! (m<-pyuiq) Moyzegsztd = Opta 

/* GHWE JO squequoa Adod y/ ‘pyuqy = (pyug<-wqTty) » 
as { 
*(XWLNAS WAFIAI) urnjez 
/(.U\i4UNYS GHW" WATII ON.) ebessou 


os fe } 
(((QHWa GI ‘WEII aI ‘3F+4) e3epdordputy 
(. xepeeHdengta) = puwq )i) JT 


TION = dew3tqzq<-uqTt 


3°QBUI}IG]8D/Sajnpow 


!(d0WNT NAITO) uznqez = ( (FFT OFULESTeg<-wqTT=55T) i) FT 


‘deep FLA 
‘Q=erqxe ‘Y QUT 
!TION = 20IZ@ SNOT 
‘Opts Zaousn 
‘Py zopeoydenata 
iS3Te STPUEHAAI 3OnTRs 
} 
(WaT Tx OFUIWATI 2OnTQAs) deuqtqje5 ONOT 
Js 
‘ssepons OJ O suanqey ~“deuytqrq<-uq{TTt sjes 
*s,WAII deep peot 03 zo ‘Hurketdstp qnoyqtm spunozbyoeq peot of 
pesn eq Aew qnq seysnzq zoz pesn AtTezeuey ‘“xGoOM eYy zr0F YyHnoue 
ebxzet asnf{ seuetd pue eaznjonajs dewata e seqesotte ‘(xqoq 3e peddoqs 
‘peszed sxunyS) eTpueHaZI peszed yATM OFUINGTII PEZTTeTATUT ue pesseg 


deurytqjzeb 


{ 
/ (UQTT) sroTODeezy 
‘ (wq Tt) dew3tqeezz 
} 
PUTT OsJUIWETI 3ONnT3s 
(wqTt) YsnzqezeTep pToa 
/ 


szoToD pue deujtq ysnzrq peqyeezD seqeDOTTeEep puke sesSOTD » 


* 
ysnzqe7eTep «/ 


{ 

i (z0z29) urNAez 
(x0ozz9) JT 
(z0z70j) FT 


+ (wqTT) UsNzqeAeTep 
¢ (qT Tt) stoTODAeb 
? (pyurg<-wq tts ‘deuytqzq<-uqTt 
‘ZZ oyUTOsreg<-ugqT Tt) Apoqpeot xzozze (z0z70;) FT 
+ (wqT F) deararqqeb Zorze 


{x0zze QUT 
} 
(WqTFx OFUIWETI 3OnNTAsS) YsnzqeAzeeID ONOT 
/* 

sseoons TOF C surNnyjey 

srOTODU<-uqTT ‘EeTQeATOTOD<-uqT} ‘deuytqzq<-wqTt dn sjes 

sZOTOD pue deuytq eyQ seh 

‘(xaoa 3e peddoqs 

‘peszed syunys) eTpueHagI peszed © YRTM OFUIWATI POZTTETATUT ue pesseg 


ysnirqezeeiD y/ 


aq’ ddeuqtt/dgzt,, epntout# 
nq reyoed/dyzt,, opntout# 
wt WqTT/dszT, Spnptout# 


*zeqnduos ebtuy-ezopoummop ey TOF UoTSIEA STYL 

06/0 Wao Aq Azerqy{‘eszedzzy~ TOF pEeTITPOW 

‘uTewop oTTqnd eyQ ut st SEZEMAzZOS STUL 

“sqry oTuozQ0eTaA ‘meYS eAegjs pue uostrz0W Arzec Aq epoo uo peseg 


(OTTa Zeuz0g ebueyoz0e3QuL st @aI) 
‘S®TTS WHII 5uypeex zoz seutynoxz jzoddns d'adWWLIALES x 


BS ETL a a ee ee a aa a a a Ee et -onnx/ 


2" deuijiqjeb/Ssejnpow 





vices 


: De 


528 ROM Kernel Reference Manual 


/ (zoxze) uznAex 
{ 

{ 
{ 
!@TIGON = xOxrTE 
/(,U\WEII we ON,,) obesseu 
‘(wqTt(. osuleszeg sade) Dera yereds 

esto 
{ 
‘(mqtt)Aetdstpeqetep ((wqTt)AeTdstpeqeez> = eieee 

((WIOd AI ‘WAIT AI ‘FFT OFULOSTLY<-UQTT) SF 3XEQUOD) FF 


/((nt\Tngzsseoons eTTzTeszed :uqTTMoys,,) nq) 
ee } 
((d00 WasadI == roxze) || (00H WaAsAI == Torre) | | (07; )) FF 


£ (syqodo gs * oyureszeg<-wqTt 
4SAYDAOSTTOo * oy uleszeg<-wqT Tt 
‘syqodozd* oyuleszeg<-wqTt 
‘MAII GI ‘WdOd AI 

‘UqTT(. OFUIEsreg QONITAs))eTTsTeszed = r0or7e 


£((at\Ingsseoons eT tztuedo Serene 


(( (waa aadI ‘oueveTTz ‘waTt(, oyureszeg Qonz38))eTTZTUedo = T0120) j) FF 
{(aoMsa ZNAITO) urnqez = ( (FF oyUTOSTea<-wqTT) j) FT 


19 = zxoxzz°e ome 
(eureueTTF¥ ALAGA ‘WATTy OFUIWMATI 3ONTAS)UqTTMOYS ONOT 


/* 
(q°oszedzzT/seTxrerqyT) wiaIAI we TO sseoons TOF Q surNq_eY » 


*suofqouns 0°Z/E°T Bbuysn zTesanok sxzojToo ey 
ebueyo nod ZF AuNoD AZOTOD TOF (OMMIOTOONWXUN ‘STOTOOU<-WTT) NIN O50 
*pasupeoT ues nok ueyqQ szoToo ezou eq Aew szojToou WeYqQ SION 


"sZOTODU<-UqT}T PUe ‘ETIeITOTOO<-uqTT 

‘dam<-uq ty ‘dxs<-uqT}? ‘da<-wq Ty ‘upm<-wqTy ’29s<-wqTT 

‘Sueo<-uq Ty ‘pywg<-wqry Suyztrepazut ‘WaTI we AeTdstp pue peot TTT 

‘eureueTTs & pue ‘sxyodojs ‘syxyoRDeTTOD ‘syyodozd pezysep pue eTpueRddr 
FFF OFULOSreZ Osn-uz-Jou & YAM YIM POZTTFIFUT OCFUINETI we pessed 


* 
* 
* 
* 
* 
* 
* 
* 
* 
* 


WAT FMO"US »/ 
fesegxgso, AzexzqyT AonzAs uzeqxe 


ut ddeuqrt/dzzt, epnTout# 
un¥ zeyoed/dzzT,, opnTout# 
oT WQTT/dsTF. OpntTout# 


* zeqndut0D ebyury—ezopoumiop eYyQ TOF woTsreA sTUL 

06/0 Wao Aq AzexqyT-esxedzzt 0Z PETS TPOW 

“uTemop oFTqnd eyy ut st ezeMaQzos sTqL 

DyuoT_OeT_ ‘meys eaejg pue uostzz0oy Axzec Aq epod uo peseg 


(Cetta qeuzog ebueqorzequr st gar) 
“setts WHII buyketdstp/butpeez zozy seut3noz yzoddng dD AWIdSIGLaD 


9 Ae|dsipjeb/seinpouwl 


2 dewijiqjeb/Sejnpouwl 


/* PUe x/ 
{ 





IFF Specification: Source Code 529 


{ 
‘ (uqtt) AeTdstpesoTo 
} 
(WqTTx OFSUINATI onzAs)XeTdstpeezz ptToa 
/* 
(szoToo jou) Aetdstpyjeb worz AeTdstp sejeooTTeep pue sesoTO » 


* 
Ketdstpeezz x/ 


(0) ‘kee 
(Tv) Sets 
(,u\"4etdstp uedo 03 petted,) efesseu 
(((pyepou ‘deep ‘yhty ‘epta ‘wat Tt) Ketds puede) i)3F 
Ketdstp eq3 wedo!s 
* 


‘ (uqTt) Bureoqeh = ptTepou = Sureo<-waqTt 


! (HLESQNYXWN‘ seueTaU<-pymq) NIW = deep 
! (aqbyeqebed<-pywq ‘q<-pywq) xu = dSTY 
‘qaptmebed<-pyuq : m<-pyudq 
& ((qaptmebed<-pyuq) seqkguou) =< ((<-pauq) seqAgmoy) = epta 


ipamq. = (pyug<-wqTts) » 


=o { 

i (XWLNAS WAFsdI) vznzez 

/(,0\xURYO GHNE'WETI ON,,) ebessou 

= = } 
(((QHWA GI ‘WAII aI ‘Z3T) e3epdorzdputz(» rtepeeHdewata) = pywq) j)sT 


‘(aowsa LNAITO) uznqez = ( (FFT OFULOSTEA<-wgTT=F5T) i) FF 


‘deep ‘ySty ‘opts qaoma 
‘Pyepow SNOTA 
‘pauq,y zepeondenata 
‘33T* STPUCHAAI JONTAS 
} 
(mqTt* OFUIWNATII 3oOnz348) AeTdstpye5 SNOT 
/* 
(y*oszedzzy/seTzerqtT) WHaddI we TO sseDoNs ATOZ O suINACeY 


dzs<-wqt} ‘daa<-uqT} ‘da<-uqtt 
4aqmM<-ugqTy ‘zos<-uwqTy ‘Sueo<-wqtTy ‘pyum<-uqTy dn sjes ‘[nzsseDdons FI 


*szexrd zesn AsesoT> ey3 uo peseq Huyreques ueosTEAC O°Z SeEOpP OBTE AI 
‘MOpUTA pue ueezDs soq-uou ZO som ‘ET 20 O°Z & suedo 3I “eTNpow 
D°ueezos ey3 ut st ()AeTdstpuedo ano - ()AeTdstpuedo euyzqnoz 

yTeuze;xe ey3 sTTeo pue Aerdstp ey z0z epouw pue suoTsueuTp ogq 8306 
‘(xaod 37 peddoys 

‘peszed syunyS) eTpuegaar peszed e& qQTM OFUINETI POZTIETITUT ue pessed 


RRR KKK KKK KKK K 


Ketdstp 305 


2°AB/ASIP}]9N/Sa|Npow 


{ 
/ (UqTT) sroTODSeeITT 
‘ (aqtt) AeTds tpeezz 
} 
(WqTT* OFUINGTII 3ORzTA4s)AeTdstpejetep ptoa 
/* 


szojToo pue Aetdstp peqeerd seAedoT[eep pue sesoTD » 


* 
Ketdstpe qertep x/ 


{ 

i (z0zze) uznqAez 

/(uq tt) Aetdstpejetep (Tore) FT 
{ 


! ( (OMRMIOTOONWXUN ‘ STOTOOU<-uqTT) NIW 
‘eTQeATOTOD<-wqTT ‘da<-uwqTt) PASUPeEOT 
(( (qT F) S20TODAeb) 5) FT 
} 


(z0z20j) FT 
!((zozze ‘,u\pTg = zozze ‘Apoqpeot zeqze :AeTdstpezeezo,,) 6nq)a 


¢ (pywa<-uq {ts ‘dew3ta<-20s<-wqTT? 
"SFT OsFULOSreg<-wqTtT) Apoqpeot = zozz9e (z0120;,) FT 


‘((xozze ‘,u\pTg = zorze ‘Aetdstpjeb zeqjze :Aetdstpeqeezo,,) fuq)a 
(uq ty) Aetdsetpjeb = zozze 
/((,u\: Aetds tpeqeezo,,) nq) a 


/Z0IzIB AUT 
} 
(UqTTs OFUINATI 2onz3s) AeTdstpejeez> ONOT 


/ 
(y‘oszedgzy/seTzerqTT) WUAIAI we TO sseDons oz OQ suInzeY 


*suoyqouns 0°Z/e°T Sutsn x Tesanok sroToo ey 
ebueyo nok st AunoD TOTOD TOF (OMRMOTOONVXUN ‘STOTOOU<-UqTT) NIN 950 
‘paoupeoTt ueo nok uey3 szojToo ezou eq Aew sxoToou 3eY3 830N 


* SIOTOOU<-uqTT 
pue eTQeRTOTOO<-wqT}T ostTe pue dxs<-wq Ty ‘dzm<-uqTy ‘da<-uwqTt 
‘uyM<-uqTy ‘zos<-wqTy ‘Gureo<-wqT} ‘pyweE<-uq{t dn sqes ‘Tnzysseoons ZI 


“WETI eY3 sheTdstp pue ‘eTqeqzoToo pue AeTdstp eq; sooTTe/suedo 
‘(xaod 32 peddoqs 
‘peszed syuny>) eTpueqaaI peszed y3TM OCFUIWATI PSOZTTETATUT E poessed 


RHR KKK KR KRKE KKK KEK EK 


Ketdstpe jeer 


* 


‘(mqTt (4 oFUIesTed ZONTAS)) ETTFTesSOTO 
/ (aqt}) AeTdstpeqeTep : 
(WqTT* OJFVIWATI 3ONI4s)wqTTAoYsUN PTOA 
/* 
wuqttmoys Aq peuedo/p,coTte butyyAzeae sesoToD pue seers » 


* 
wqTTMoysun »/ 


> Kejdsipjeb/sajnpow 





Devices 


530 ROM Kernel Reference Manual. 


/s' Kadwo ATAuezmno sy r90sING »/ ‘eztsynq + zSezszZnq = Jnq 


/x° 2ZzTSZUC SOTFTPOU WOTAIeTSRT 3sSeT -SAIAIGOW + 
*“smox ssezduocep pue seuetd eaeeTxreqUT-eg » 
*dew3tq ¢,3UueTTO ojUT sqUeQUOD AGOG ETI PeeY +/ 


Sseqkgqmoyors =- eztsznqg 

fseqkqmoyors =+ zeszznqg 

sreyznq = yseqT Inu 

/«*seuetd pequemun wory smox zo uoTReuTysep Aummp xox yuTs e dnjes x/ 


{ 
/x* UND ut euetd yseu epntour x/ ‘/T =+ QuoeueTdors 
/x° O28 ueyQ seUeTAysp ero esed UT x/ ‘TIAN = (quoeuetgozs] seuetd 
este 
/*°83Y% exozeq szequytod-eueTd TION ©q TITM ezeyy ‘seueTaIsP x 
ueyy seuetTdors erou ere ereyj JI x/ ‘xAseU = (qupeuetaozs] seuetd 
(TION =i 4seuU) FT 
} 
(yseyseqysu == 5uptyseu<-pywq) FF 
/*°20Ts ,seuetd, 5up~puodsezzo> ojut zqd ouetd yseu Aue Adod x/ 


!TTON = [oueTat] souetd 
(+40ueTadt ‘seueTgorsxeWM > eUeTdt -/ ) OZ 
{[euetat] soueta<-dew3tq(, abxa) = [ewetat] seueTd 
(++0ueTat /q3deq<-deuwqtq > euetTat ‘0 = eueTdt) OF 
/x°'sq0Ts Xqdwe ut TION /s23d dewatq yqym ,seuetd, Aezze eztTeTATUL ¥/ 


‘((qqdeq<-deuwqtq ‘seuetau<-pyuq ‘smoyu ‘se qAgmoyors 
+,U\pTs=uadeaqsep ‘prg=aadeaors ‘pTs=smoyors ‘pTy=seqXgmoyors :z7Apoqpeot,,) fnq)a 


‘smoy<-deujtq = smoyu (smoy<-deu3tq < smoyu) JT 
‘((ua\syDeyo uotszeauoD ysed :zApoqpeot,,) 6nq)a 


‘ (dowaa LNATIO) uznjez 
( seueTgoxrsxen < QupeueTqors 
I] Z « seqkgqmoygng > eztsznq 
|| mogzegseqkg<-deuztq < seqhgmoyors ) FT 
/x° OTpuey 2,UsSeOP AGOMISH woTszeauoD e& TOF pexse AUSTTS FF utertduop »/ 


{((qupeuetaozs ‘seqXquoygnq ‘eztszng 
‘,U\PTS=quoeUeTaOIs ‘pTs=seqkqmougng pTy=ezTsznq : zApoqpeot,,) Suq) a 
! ( (noazeaseqhg<-deuqtq ‘seqkqmoyors ‘uoptssezduo 
+, U\pTg=seqigdeugtq prz=sezAgors pry=uctssezduop : zApoqpeot,,) 6nq)q 


! (dowaa ~LNATTO) uzn302 
(TunyeqyAgdum < uofssexduop) JT 


2 (FFF) AUNGOQUeTAND = wd 
/ ((seqhgmoyorzs ’,,u\pts = seqXqmuoyozs,,) 6nq)a 


Udy SPONQxe QUOD AONnzZAs 

/« 4s8eu 9 soueTd 03 sxqd go Aezze ,/ ‘[seuetTgorsxey] souetd, AaLAd 
‘qseqdy, ‘JNGTINUy ‘QSCECTINUy ‘FNqy ALAC 

‘PETTTaU GUOM z04sTbez 

‘Kaduqu ‘moyt ‘euetat ut z0eqstbex 

fuopssezdmoo<-pyuq = wofTssexduo> CuOM 

Jq<-pyuq = smoyu QUT 

/ (seqkgmoyors) eztspeyoeaxew = seqAgmoysnq SNOT 
‘moyzegsezAg<-deuytq = seqkgmouj3sep MuOM 

/ (m<-pyuq) seqAgmoy = seqkgmowors GuOM 

/x30K euetd yseuw rozy pequnod 3,ueEeAseH x/ /seueTau<-pquq = quUDeUeTdoOrs aALAGN 
} 


teztsynq ONO 


2" JWIG]I/Sejnpow 


{ZOFINGs, ALAC 

‘pquq, zepeoxdenata 

/yseuy FLAT 

‘dewjtq, dewata qonz3s 

‘FFTx SOTPUCHAAI BONIS 

(eztsgnq ‘zezznq ‘pywq ‘yseu ‘deuytq ‘33+) cApoqpeoT SNOT 
/x KGOUISD PTO OY OATT ¥/ 


{ 
/ (zr0zrzxe) urnNAeEZ 
! (eztsznq ‘reFzNq) weyeerTT 
{ 
/((zozze',,u\pT% = zozze ‘Apoqjebh worz peuznjey,,) nq)a 
i(eztsgznq ‘zezznq ‘pywq ‘TION ‘deuwjtq ‘334) ZApoqpeoT = r0z70 
= { 
‘(WEWON WAIAII) uznqexz 
‘((ezFsznq’,,U\peTTes PT JO SoTTe pesrnae eens 
(( (19 ‘ezTsznq)we_OOTTY = TZZNq) ji) FT 
ty >> ((a<-pyuq) soqAgmoy) ezTSpexDeaXeW = SzTSING 


£((.0\pyuq pue deuntq pasa )opaa 
((pumq) 33 (dew3tq) ) st 


{ 

S(AWHO aI) uznqexz 

*(nU\ACOG OU seq Mentone 
(((xao@ aI ‘WHII GI ‘FFF) STAUNGOJUeETIND) j) FT 


/* ©390Ted © 5,97 eqkeH x/ 


‘((.t\4poqpeoT ur,,) nq) a 


2 T = zrorze ONOT 
feztsznq ONOTN 
fzezzndy 7 
‘pyuq, zepeoydenata 
‘deuqtq, dewata 3onz3s 
!FFF* STPUBHATI 3ONTAS 
(pqmq ‘deuw3tq ‘33+)ApoqpeoT SNOT 


fesegxgos AzexzqrT qonazys uzeqzxe 
(gz) seueTdorIsxen euTyopH 
weyAdop wewacu eutyep# 


aq ddeuqtt/dgz}t,, epntout# 
n¥ zeyoed/dzzT,, epnTout# 
eG WQTT/dzzT,, OpnNTouT#F 


*zeqnduoo ebtuy-ezopoummtop egy XOF uoTsreEA sSTUL 

06/so AzexrqyT“eszedzzt TOZ peTFTPOW 

‘utewop oTTqnd ey3 ut st exeMQzos sTyL 

‘sary oTuozQ0DeT_ ‘meys eaegs pue uostxz0o_ Axzzec Kkq epod uo peseg 


(‘eTTA yeuzog efueyoxreQqurl st gar) 
“sets WAIL bButpeez zoz soeutqnox yzoddns d°uNaTI 


eKEK KKK KK 


* * 
~ON 


/x @Szedjz} YATM ESN JozZ souTqnoz ButpeoT WATI --- O° TUqTT 


2 JWIG|I/Sejnpow 





IFF Specification: Source Code 531 


xequmu 03 sToToou<-uqTT Hutaqes ‘QT O4UT STOTOO qYWD SpeoT pue x 
OMMIOTOONWXWN SPOT 3B TOF STQeATOTOdS<-uqTT eB seqeDdoTTe - szoToOD eb y/ 
{ 
40 = eZTsqeqo<-wqTT 
TTION = STQERTOTOO<-wqTT 

{ 
{ (ezpsqeqo<-wqT} ‘EeTAEITOTOO<-wqT F) wWeyooT = 
} *(AWHO GaI) wznqez 

(@TQBQTOTOO<-uqTT) FT { 

} { 
(wqTt* OFUIWAII JONTAS) STOTODSETF PToA { 
/(seqAgmoyors - seqdqmoujsep) =+ qseqdy este 

?(QU'TIONWN WAAAI) urnyzez 

{ /x seqkqajsp ‘seqXkgors ‘qseqd ‘eoxnosd x/ 
{ (z0zz@) uznz0er ( (seqkgqmoyorzs ‘petttau ‘qseqd ‘gnqy)mozyoedun ) ZT 
! ((zozze/szoTOoU’,U\PT% = TOIT :sXOTOD pTy Foxy eTQeqroOTODDOTTe,,) 5nq)a /x  eueTd uoTAeuTAsep of MoT ssexrduiopeq »/ 
= { } 
{WOAON WAAAII = Tore este 

{ { 
{fo = z0zze JseqAgmouqsep =+ y4seqd, 
Jeztsqeqo = ezTsqeqo<-uqTtT fseqkgmoyors =+ gnq 
fszo[Toou = sxzoToou<-uqTT a i (seqkqmoyorzs ‘3seqd, ‘ynq) wewnow 
— - } /(QH'IOSNWA WAIAGI) uTnqer «=(seqkgmowors > PETTTAU) ST 
((OITHNd AWEWN|UWAIO ANEW’ SZ TSqeQD) WeRDOTTY(* PIOTOD) } 
= STQRATOTOO<-ulqTT) FT (euondu == uotssexduod) xT 
‘(pPIOTOD) FOezTsS y% STOTOOU = ezTsqeqo /x oueTd uotqeutysep 03 Moz pessezduiooun Adop x/ 


[x cc----- ------ sxojTooqeb 


esto 


! (DMMIOIOONWKEN ‘STOTOOU) KYW = SzTOTOOU 


= { 
/* QWWO ut Auew moy y/ ‘¢ / ezts ds<-ds = szojoou to Aqdurgu 
/* fezTsynq = peTTtau 


poou om eTqey ezts eYyQ eqnduoy » {zezynq guq 
x/ 
} 


| {(4OWaT LNATTO) uanqez 
((a¥NO GI ‘WAIT aI ‘33t) dozaputa = ds)3t (Kadugu > (Aadwgu ‘[petttau]zesgnqs ‘337) seyfqyunyopeey) st 
/x"B yep Hbutastxe eyQ 09 eQep mou pueddy x/ 


{(aowaa LNATIO)urnqer = ( (FFF OF UTOSTea<-wWqTT=3FT) i) FT , 


‘szojToou ZaoHSsSN /* Yuy-you y/ ‘Aaduwgqu + petitau = eztsynq 
a feztsqeqo SNOTO / (uo) seqAgezoyxunyo = Aqdugu 
‘MOWwT BNFITO = z0z770 SNOT /x° XOEFFNQ SYR TTTF C2 3FOT seqkq ySnoue 7 ,uerTe SereuL me 


tds, Aqzedozgpezojs  yonzAs 
35Te STPUBHATI WONITAS 
} 
(WQTTx OSUINGII ONTAS) OTQSATOTOOOOTTE ONOT 


/* 
‘eTqQez SYA UT TOF wWoor eAeY EM SIOTOD FO TequMU eYR OF 
SIOTODOU<-UGTT SJES PUES STASZTOTOO<-uqTT SEABDOTTE - STQEATOTOODOTTE +/ 


{ 
/ (z0zze) urnjex 
/((zozze/,U\pT% = zrozze :sz0T0D 306,,) nq) a 
{(uqT}) stoTODeeTZ (OTIS) FT 
/ (sxOTODU<-uUqTT? ‘OTQeAZTOTOD<-uqIT ‘ZJF})dewopeoT = rorIS 
(((aqTt) eTQeATOTODSOTTe = TOrTIe) j) FT 


/(a0WaT ENAITO) uznqexr = ( (FFT oF UTSSTeg<-wqTT=353T) i) FF 


iT = zoxzxe Aut 
*33Te STPUeHAAI WoONIAS 
} 


( (ud) seqkgozopyunyo < Aqdugu) st 


/x° Se fq 9 Bbutaou eq ptTnop «/ <{(peTTtgau ‘zezznq ‘Fnq) weunocu 


/*° (T-PETTTAU)] rezznqQ* * [9] reFFNq ebuez sxeA0D MON »/ 
/x XEFFNG eyRZ FO QuorzZ eyQ OF eQep HutTAstxe ey eACH x/ 


/x° STOW PBST OF PEON x/ 
} 
(seqkgmougngd > PeTTTau) FT 
/x"e3ep sey gazed stuy «/ ‘Aqdugu - eztsznq = peTTtau 


/s°zezznq Fo yxed Aydue jo ozts x/ fzezgznuq - gnq = Aqdugu 


/x°MOX Qxeu ssexduiooun 03 seqkq ySnoue yseeT 3e UT pESy x/ 


{ 
‘JNATTAUS aseoad 
‘4seqttau snqTTau 
} 
(TIAN == 3seqdx) 3T 
/x euetd pequemun Aue zoxy yuTS & YSTTQeysaT »/ 


/{euetat]seuetds = qseqd 
} 


vices 


: De 


(WqTTx OFUINATI 3OnTAs) sTOTODAEH ONOT (+4+0uUe Tat /QuDeUuReTGOIs > SsUeTdT ‘0 sueTdtT) r0F 
/* } 


*pepeot AtTTenqQoe sIOTOO Fo * (--mout /0 < Mout ‘smMoyuU = MOYT) TOF 


o-WIg]!/Seinpow > IWIG]!/Sejnpow 





532 ROM Kernel Reference Manual 


{ 


2 (pFepour) uznzez 
/ ((ptepou’,,u\xTs0%$ = pTepow : fueDeb,,) nq) a 


{ 
‘ ((pTepour’,,u\xTs0%$ epou Suysn - punoz OWWO ON.) Snq)a 
= . { 
‘WWH : QLTSGs1WH WULXa ¢ a@Ha<-wqTT =| pTepow 
} 
(9 == deep) 3T 
‘OWI =| prepou (oom =< G6tq) ZT 
‘SHUI = pTepou (ov9 =< epta) L 
* 
*sepou peqnduos esn ‘/quesexd (SWWO PEq XO) SWWO ON x 
»/ 
} 


{ 
‘tInan=ds (((000T0000X0 3 PTEPow) j) 339 (0O00TAaAXO 9 Pee ee 
* 


“PIOM XOMOT UF 3ES AOU x 
atq pepuejxe pue prom zeddn ut yunl qQtm » 
seysniq IIQUTedd EATT OMWO snboq roxy yoyo »/ 


!((3QIH aAlO@aIA NOOINED|OIGaW NOOINS| SaLIuds|ZqoW GaaNaLXa) ~) 
iz =3 pTepou 
((((00004aa42%0 3 PTEpour) ;) 99 (ATGOW GAGNELXA 3 PTepour) ) 
|| (CQISWNH GI YOLINOW 3 PTepou) j))FT 
/* 
SQA epoumeta 3Tq-9T eTA3s-pTO FO yno s3Tq peq Yooux »/ 


i(eqeq ds<-ds (» SNOTO) *) = pTepou 


2" JWIG]I/Sejnpow 


(dsj)3t 


a = } 
((QWWO GI ‘WHII GI ‘334) dozaputa = ds) ZT 
/* 
“sepoumeTA SYR JO POPT S,ONWO APIO x 
x/ 


/( (deep ‘ySty‘epta’,,u\WETI PT$=P PT$=4 PT%=4 TOF OWWO 5uT33e5,,) 5nq)a 


/soueTau’ pyug<-uqT? = deep 
‘qybteqebed: pyug<-wqTt = ySty 
‘qaptmMeded: pyug<-uqTy = eptm 


‘(To)uzngqez = ( (FFT OFULSSTEg<-UqTT=35T) i) FT 


*I0 = ptepouw ONOIN 

ideop‘ySty’epta ayomn 

tds, Xqzedozgpez0ys AoOnzRAs 

*FFTe STPUCHAAI QONTAS 

} 
(WqTTx OFUINATI 30nz3s) bureoqe6 SNOTN 
/* 
“TTeS styZ oF zoTad pezTTeTaTUT eq Asnu eINQONIASs PyUE<-wqTT ¥ 
* 
Bureo<-uqtTy ut eberojs oF epouwu peqnduosd zo OWNWD surNzey x 
x/ 


{ 
/ (0) wznqez 
{ 
J+4+2PTF 
| 6 | z = [xpt]etqeqzotoo 
fy << ++q6zy q 
40ax0 9 ++q67y% 6 
fy >> (oax0 9 ++q62%) z 
} 
(--szoTODU) eTTYM 
70 = XPT 


iszo[Toou = sroTOoNd, 

{szo[TOoNd, = szoToou (sxoToou > SZIOTOONd,) FF 
‘zeqstbheyzoTooszoezts / ezts ds<-ds = sxojoou 
feqeq ds<-ds = q6z 


*(T) uznqex (((awWO GI ‘WaII ax ’33t) dozaputa = ds) j)3T 
{ 


‘(T) uznqez 
2 (,B\peqeooTTe eTqeq_zoTOD on,,) ebesseu 
} 

((@TYBITOTOD) j) FF 


iq ‘B ‘zx SNOT 
iqb2% @LAGN z0qsTbez 
iszojToou NON rz94sTbex 
!xpt SNOT z0qsTbez 
tds, Ayjxredozgpezoys Aonzqs zeqsTHbexz 
} 
(szoTOONd, TYOHSN/STASITOTODy CUOM ‘FFTx STPUCHAGI 3ONTAs)deuppeot ONOT 


/* 
IMOHSN & 03 zeqUTOd e pessed st ouo sTUL 
sxoToond zoy a@LxGN & 03 reqUTOd © pessed GYNDIED PIO - iii ALON 


‘peez ATTenqoe zequmu 9yA OF sIOTOONd sqes pue sTOTOD eyQ speOoT 
‘pToy 03 eveds sey ZeTTeS sIOTOD Fo zequmu Hututequoo TUOHSN e& 
03 zequtod pue ‘Aezze eTqeqrotToo oj requtod ‘eTpueyadI pessed 


AWg|I/Sejnpouw 





: Source Code 533 


IFF Specification 


(dowaa BNAITO = OSS) esto 
at { 
2 (3LIIM WAFAII) wznqez 
(ze3s8TbeyzoTopsyoezts =; 

((zeqsTbeyzoTopzoezts ‘hbeydewoy(, LAG) ‘FFF) SoqATXUNYDSRTIM) ) FT 
iszyJo =+ eqeq 
¢eqej, = oentq* Seydeuo 
isyyo =+ gqeq 
‘gqeas uee26 - beydeup 
isyyo =+ gqeq 
‘eqeqy = Pee 

( szojToou-- ‘szojtoou ) z0z 

‘y > tT é (8 s= unbzedsqtq) = szzo 

feTqeqzojToo (» aLxAan) = 

((ze == unbSzeds3rtq) 11 (¢ == ees este 
{ 
i imqeg++ 
?(SLIIM WAIIAI) wznjez 
(z038 beyroTopsoez ts =j 

((zeqsbeyzoTopzoezts ‘Seydewoy(s aLAG) ‘F34) seqAqyUNYOSZ TIM) ) FT 


(yp << entq*beydews) =| en tq’ Seydeuo 
‘o3x0 3 ( b >> mqede ) entq: beydewd 


£(p << useezb:boydeuws) =| uw0e08ex6*beydeu> 
‘os7x0 3 ( Mqeax ) uweexrh * Beydeu 


pez * beydeu 
pez Seydeu> 
} 

( sxojToou-- /‘/szojfoou / )z0z 

F@TQEATOTOD (¥ GTYOMA) = AqeQ 

/x« Wa se U ONTeA ATqQ-p yore er0RS x/ 

} 

(py == unbzeds3tq) zt 


i(y << pez: Seydeu) 
‘o3x0 9 ( w << Mqegx ) 


/((zozz8',,a\pTs = zorze ‘ayWO GI peysng,) 5nq)a 


_ / (z0zze) uxznzez 
((xeqsTbeuroTooszoezts » sxoToou ‘aWWO GI ‘TION ‘334)xUNYOYsNd = roe) FT 
/x szoToou » seqkq € ST GUND JO EzTs x/ 


!(a0waa LNAITO) uznqez ((etTqeqzoTooj) | 1 (FF Ti) FF 


/((,t\avnoand ul) 6nq)q 


{Hbeydew z0e38TbeyrojToo 
*8Q234 FLAGO 
‘Mqe3% CaOM 
iszzo ‘zozze Huot 
} 
(anSzedsatq quoma ‘sxoToou ayiomo 


‘OTQEQIOTOD ULAW ‘FFTx STPUCHAAI 3OnzIA8)deuognd buot 


(2¥WD 09 UeQQTIM eq TTTM unb yoee Jo sytq aybte ySty eyy ATuo) 
*DJe qouGSU FO SONOIN BT ETQeAToTOD ‘ze=unbredsytq ZT 
(4¥HD © SXTT) “9390 qougSU Fo seqXq sy eTGeQIOTOD « ‘g=unbreds3tq FT 
a5uO SeTAQTU qaTM yore ‘spI0M sy ETQeRTOTOD ‘p=unbzeds3tq ZT 
isuz0oz ButmorTtjtoz 
eq3 FO SUO UT senTeA TOTOD Jo eTqeyA e Adeooe TITM woTRoOunsZ sTUL 


2" MUIQ]I/Sejnpow 


/* 


a = = { 
!( AWHO ddI : WowUT INEIIO < (seqAgmoxz)ado SI )uznqez 


{ 
!T << qoedsyX<-pyuq = yoedsyA<-pymq (JOVI 39 PTEpou) FT 
iT << qoedsyx<-pyuq = joedsyx<-pymq (SHYIH 3 PTEpow) zt 
'@G : py & Twa 3 sbetaXketdeta<- (eseqxgo(, osegxyD QONTR5) ) 
= qoedsyf<-pyquq 
‘vr = eee hoe 
(qoedsyx<-pquq ee 
* 
ofqez qoedse Bbutssenb so 
poyjew pro esn ‘pettez eqeqoszurAertdstqqey ro ¢°T zepun Huyuunz JIT y/ 


{ 

{ 
qoedsyX<-pyugq 
qoedsyx<-pyuq 
oe } 

((pyepow ‘asia vad ‘ (osurkeTdstq yonz4s) yoozts 
‘Ia3(* 3LxaN) ARRANGE EN ESe lea waaeene 
(9€=< uOoTszEA ATT<-esegxsD) ST 
/* 2% 206 04,0M u0eYyM TTEQ Wed eM Og y/ {0 = Qoedsyx<-pywq 


{X* uotqntosey "Ida 
{xX° uot AnTosey Id 


‘qybteqebed = qySteoqebed<-pyuq 

‘qaptmebed = yqptmebed<-pyuq 

SzoTooquezedsuez3 = roTopjuezedsuez3<-pyuq 

‘0 = Tpeazesexz<-pyuiq 

fuofsseaduos = uotssexduos<-pyuq 

‘6butyseu = BSuyyseu<-pyquq 

‘qqdeq<-deuw3tq = seuetgu<-pyuq 

/+°(0‘0) S¥ uotatsod 4Tnezeq x/ to = A<-pyuq = x<-pyuq 
faqbyey = y<-pquq 

iqapTa = #<-pyurg 


‘((ut\GHNaTUI ur.) Snq)a 
‘mogzegseqXg<-—deuntq = seqkgmoz MioM 


‘rq ogurketdstq 3onz38 
fesegxy, AxzexrqyT QonzAs uz08{xe 
} 
(pTepow ONOTOA 
‘aqbyeHebed auom ‘qaptmebed auom ‘aqhtey auom ‘U3PT™ CuOM 
‘xoToDquezedsuez3 quom ‘uotssezduoo quom ‘Suyyseuw auomM 
‘dew3tq, dewata qonzys ‘pyuq, zepeeydenata) pymqytuy Buot 


fesegxgo, AzezqyT Qonzy4s uz68eq4xe 


<yeseqxz5/sotyderb> epntout# 


uq*reyoed/dzzt,, epntout# 
ws UQTT/dszt, epntout# 


[emer Sce reese sae aes ek RE eh a i trie es em aca ele 
*zeqnduos ebjtuy-ezopoumiog eyQ x0F UOTSIEA STUL 


‘ufeuop ofTqnd ey uy st ereMQzZOs sSTUL 
“sqaW OTU0TQDeT_ ‘meys eaejs pue uostrz0oW Arzzec Aq epoo uo peseg 


(‘eTTa yeuzog ebueqorequI st JaI) 


a aaa tat a a et en am Betas SsSasas assesses aeeesnsecg/ 


o"MUIG]I/Seinpow 





vices 


De 


534 ROM Kernel Reference Manual. 


{ 


/ (zoxze) urNACeZ (xoxzze) FT 


2 { 
‘QLIUM WUFIII = 0179 
(seqkguoypoyoed =; (soqkgquoypeyoed ‘zezznq ‘ZZ 7) seqAqyuNYyoSyTIM) FT 
‘(seqhgmoz ‘gnqy ‘[euetat) seuetds) mozyoed = seqkgmoypexoed 
/zezgnq = znq 
} este 
/*° MOI 3XOU EATIM pue sserdu0D »/ 


{ 
‘seqfgmoz =+ [ouetat] souetd 
*GLIUM WAIGII = rOTIS 
(seqhgmox =j (seqAgmox’ [ouetay] souetd ‘zz }) soqAgqyunqoe3tiMm) JT 
} (euondus == uotssexzduos) st 
/-°MOZ QKOU OQTIM x/ 


(++0ueTat /quoeuetd > euetTat ‘0 = eueTdt) xz0F 
} (--mout /0 < Mout /Y<-pywq = MOYT) TOF 
/» 83UeQUOD XGOM SYR 3NO S3TIM x/ 


{(zozzxe)uznQez ((NMONIND AZISadI ‘XGOM GI ‘TION ‘33T)AUNYOYSNa = TOTIE) FT 
/« zepeey YuUNYS AGOM & 3NO O3TIM +¥/ 


‘yseu = (q3deq3sp] seuetd 
(TION =i 3SeuU) FT 
/[euetat] seueta<—deuwjtq(, gaixq) = [euetat] souetd 
(+40ueTat ‘yqdeq3sp > euetat /0 = eueTat) r0F 
/» ,seuetd, Kezze TedoT oquy seuetd yxsew 9 3tq 073 srA4d eyQ AdoD x/ 


4(T : 0 é TION == ysew) + yAdeqgsp = quoeueTd 


‘(SoMa LNAITO) wznqez 
/xeutynozr styz rox Aueu 003 ( HL@GagAYSXEN < y3deaqsp 
/* JUEASTsSUCOUT I] yadeaasp > y3deq<-deuwatq 
/x3UEASTSUOOUT Il (a<-pyuq) seqigmoy =; seqhgnox 
/* JASE YSTsUCoUT Ul q<-pyuq =| smoy<-deujtq 
/+ 6xe peq Il Tanyeykgduo < uotssezduos. 
/sMoz psiduoo e zezxznq 3AsnW tt (saqAgmoz) eztTspexoegxeW > EeZTsznq ) ZT 


‘((.u\xdogand uz.) 5nq)q 


/» 18ea 9 souetd 03 szad zo Aezze y/ ‘/[T + HLaaCaAWSXWN] soueTdy FLAG 
30d, ALA 
‘seqkgqmuoyupeyoed ONOT ze qstTbex 
‘Mout ‘oueTat Quy zeqstbez 
/+ 3%sea Buypntout seuetd 3¢q Fo Tequmu x/ /qupeuetd aut 
Juopssezduop<-pywq = uotssezduioo aLxGn 
/seueTgu<-pyuq = yydeq3sp UT 
‘moyzegse zig<-deuwqtq = seqXkgqmoz SNOT 
‘zoxze Buot 
} 
(ezTsznq ONOT ‘TEFFNGy ALAC ‘Pywq,y zopeeHdenata 
‘yseuy gzzq ‘deujtq, dewata 3onz3s ‘33T» eTpueHaaI 3OnrT9s)Xpoqajnd buot 
/« °(®372M SOG OF SeTOJFOTEYI » 
pue) seqhgeqtamadI 03 sTTeS Temes rez SyeW ptnom AT “zezznq potiddns » 
ey JO STOW pesN AT JT aeaaes LOT & Sq PTHoOD uoTAeQueUeTdUT STUL “ALON x/ 
/4------ Apoqand ------- aana/ 


{ { 
/ (zozze) uznqez / (z0zxe) uznQez 
(FT) HunYOdog = rorzze (33) yanyodog = z0zz9e 


/x MANY CY UsStuta x/ 
{ 


2 MWG]I/Seinpow 3° MUIQ|I/Se|Npouw 


/((z0zze’,U\pT% = z0zrze ‘szeqstbez 2©302M,,) nq) a 
\ 





Source Code 535 


IFF Specification 


x 
WAT TPCT +/ 


i (r0zze) urnAez 
{ 
! (uqTT) must oeete 
{ 
!Q@IIGON = r0zzxe 
‘(,0\WEII ue 30N,,) bessou 
} 
este 
{ 
‘@TIGON = 1TOrxe ests 
{ 
{ (aqTt) Bureoqeh = Gures<-uqTt 
‘pug, = Cates 
((GuWa GI ‘WHIT ar ‘FFT osUTSszea<-wqTT) eyepdozdputs 
(,zepeepdenata) = Pra, 
((WaOd AI ‘WAIT AI/F34* OFUIOSTeg<-UqTT) STAXOQUOD) FF 
sa = } 
((40% wagadI == zozze) || (90a waaddI == rorre) | | (1077; )) FF 


/((zozze’,,u\pt% = zozze ‘eTTzZTeszed z09eqze :wqTTAzenb,,) 6nq)q 


!(sdoqsAzenb ‘TInN ‘sdozdXzenb 
‘WATI GI ‘NHOE AI 
‘mqTt(, osureszeg jonz48))eTTsyyeszed = xrozz0e 


£((,a\tazsseoons eTtztuedo :uqttAzenb,,) nq) a 
= } 
(((awaa agar ‘oureueTtz ‘wqTt(, oyuleszeg yonz3s))eTTFTuedo = r0z10)j) FT 


{(aowaa BNEITO) urnjez = ( (ZZ 7“ oFUTEstea<-wqTT) i) FT 


‘pquq, zepeeyqdenata 

/Jo = x0zzxe SNOT 

} 

(eweueTTS» ALAN ‘WATT, OFUIWHII JOnr3s)wqTTArenb ONOT 


_!{ aNod OVE 
‘xQ0@_dI ‘WHTI_aT 
‘aQ¥NO GI ‘WII aI } = []sdoqsXzenb 9NoT 
Js peyoeez st XGOG A° dYWO & wEyK do js wes uweos a/ 


_‘{ aNod S¥a 

‘OWWO_QI ‘Wa'II_dI 

‘GHNG GI ‘WHII aI } = []sdoxzdAzenb onoT 
/* syanqo eseyQ squem qsn{ Azenb ,/ 


/* 
(q°oszedszt/setzerzqtT) wugadgI we TO ssepons r0Z O suUIN_AeY » 


“aate Teep oj quem not edXQ 
pue ezts © st WHII S43 FF SUTMZEREp OF NOA SMOTTE STUL 


“WHII CYR SSOTO pue 
‘pyuq<-wqT} pue Sueo<-uqry ut TITS ‘A@II ue uedo TTTm 
‘eueueTTy & pue 

‘OTPUCHAII OSN-UT-JoU & YATM OFUIWATI POZTITIFUT We pessed 


KEK KKK KK 


* 
uqttAzenb »/ 


o-wiqg|ipeo|/Sejnpow 


‘ (aqTT) ysnzqezeTep 

‘(UqTT (x OFULesTe_ ZONIAS)) eTTFTEsoTO 
(WaT Ts OFJUINAII 3ONI3s) ysnzqpeotun Sioe 
ysniqpeot Aq peuedo/p,ootte ButyyAzeae esoTD pue aces 
ysnazqpeotun */ 


/ (z0zze) uznN_eX 
{ 
{ 
{ 
!37IGON = zx0zz0 
£(uU\WEII ue QoNn,,) oHessou 
‘(wqTt(¥ oyureszeg RONTAS)) EeTTFTeEsOTO 
} 
esto 
{ 
* (WqTT) YsnIqejeTep ((uqT}) Ysnzqeqeez> = z0770e) ZF 
= _ } 
((WYOd GI‘WATI AI ‘FFT OFUTSSTET<-uUqTT) STAXOEQUOD) FT 
= = } 
((403 WAIAGI == zorze) || (DOA WaAAAI == rOTTE) | | (tOTTE;)) FT 
/ (syqodo ys‘ oyuleszeg<-wqtt 
‘SYYDQDET TOO oy uTesreg<-wqT Tt 
‘syyodord* oyulesreg<-ugqit 
‘WATI GI ‘WHO AI 
‘UqTT(, OFUTesTeg yoNTAS))eTTFTeszed = xroIz90 
a } 
(((qwaa daaI ‘oureueTTzy ‘wqTt(, osyuzeszeg jonz3s))eTTZTUedo = z0xr7Ie) j) FT 


{(Sowaa ENAIIO) urnqez = ( (FFT OFUTOSAea<-wqTT) j) FF 


?JIQ = 2TOIISG ONOT 
} 
(oweueTT3» ALAGN ‘WTts OFUIWETI 3Onz45) ysnzrqpeoT ONOT 


/* 
(q‘eszedzzt/seTzezqtT) WAAddI we XO sseDons TOF O sUIN_eEU » 


*suotqouns 0°Z/e°T Bbutsn zTesanok sxojToo ey 
ebueyo nok Zt QuNoD ZOTOD T0Oz (OMMIOTIOONWKUN ‘STOTOOU<-uIqTT) NIW &s0 
*paoupeoy ued nok ueyQ szojtoo ezou eq Aeuw srojToou 3e43 &I0N 


STOTOOU<-uqTT pue ‘eTqGeAToTODO<-uqTT ‘deuytqzq<-wqTT 

‘fureo<-uqT} ‘pyug<-uqtyt dn Suyqqes ‘ysniq & se WaATI we PeCT TTT 

‘eueueTTzy pue ‘syyodoys pue ‘syqoQDeTTOoD ‘syyodord peztsep pue eTpueyaar 
ZF} OFUTSSTe™ osn-uyt-Jou & YAM OCFUIWETI PSOZTTETITUT ue pessed 


* 
* 
* 
x 
* 
* 
* 
* 
* 


ysnzqpeot x/ 
fesegxg5, Azezqtd qonzy4s uz0eAxe 


ua ddeuqtt/dzst, epntout# 
oT UGTT/dsFF, Spatout# 


/* 
BOUTANOT PEOCT WATI TeaeT-ySTH » 


* 
Wa zeuddeyos “5 1T6/SO D°WaTTPEOCT «/ 


oO wg|Ipeo|/Sejnpow 





vices 


: De 


536 ROM Kernel Reference Manual 


/ (xozze) wanj_ez 
{ 

{ 
{ 
*ATIGON = Ore 
‘(,U\WEII we 30N,,) obessou 
i (mqTt(, osurleszeg 3On738) Jenaiesor: 

este 


{ 


! ( (OMMIOIOONWVXWN ‘ STOTODU<-wqT FT) NIW 
‘OT QEALOTOO<-uqT F ‘ITOUMOFA<-1T098<-UqTT3) PASUPEOT 
(( (aqT fF) stoTCOD 305) ee 


(zozz0j) 3+ 
/((z0zz0’,,u\pT% = zozze ‘ApogpeoT zeqze :wqTTpeoT,,) 5nq) a 


/ (pawa<-wq tts ‘dewita<-z0s<-uqT Tt? 
‘ZzFT OFULEszeg<-wq Tt) ApoqpeoT = z01r70e 
} 
((WaOd AL‘WHII GI ‘JF OFULSSTeg<-wqTT) styxEQUOD) ad 
((d0d WIIIAI == TOT) || (D0F wiaaAI == z0r7e) | | (tore; )) FF 


2 ((zozze’,,u\pT% = zrorze ‘eTTsFesred z0eqze :wqTTpeoct,,) nq)a 


/ (syqodo js * oy uleszeg<-uqT Tt 
4sYYOROSET TOO" oyUTesTeg<-UqTT 
‘syqyodord' oyuleszeg<-uqTt 
‘WMATI GI ‘WHOA AI 

‘mqrt(, oyurleszeg WonzA4s))eTtTsyTeszed = xroxrzTe 


‘((,a\tagssepons eTTzTuedo :uqTtpeot,,) nq) a 
} 
(C(awad daar ‘oweueTTz ‘wqTT(, oyureszeg 3onz3s))eTTZTuedo = zorzTe) i) FT 


! (dowaa_INAT TO) wanqez (z9s<-wqTTi) FT 
‘(MOUUT LNAIIO) uaznqex =( (FFT OFULSESTEG<-WAqTT) i) FF 


/((.@\:uqTTpeotT,, ) 5nq) q 


!I90 = zr0zx® ONOT 
} 
(eureueTTF» ALAGN ‘WqATTs OFUINETI ONTAS)UqTTPeCT ONOT 


~~ 
* 


qxequop peszed e443 SAeDOTTeESp pue ETTF ey SsOTO OF 
(uqTt ‘JFT)OTTFFSESOTO TTeo Asnu nox “syunyoO Tey Qo euyturexe ro 
Kdoo ues noX os uedo etpuegaaI ey sdeexy ()wqTTPeOT - ALON 


(y'eszedzzyT/sotzezqtT) WaFdAII we TO sseDpons TOF OQ surNnzeY 
/ (wq Tt) srOTODeezz 


‘(watt (. oyureszeg QOnz348) ) eTTFTEsSOTO “suotqouny 0°Z/e°T B5utsn zTesanok szoToo ey43 
} ebueyo nod xf AuNOD TOTOD TOF (OMMMOTOONWXUW ’ STOTOOU<-UIqTT) NIN S50 
(WaTFx OFUINETII 3ONIGs)uUqTTpeotTun pToA *pasupeotT ueo nok wey szotoo ezou eq Aeu sxzoToou 3eYQ 2390N 
/* 
wqttpeot Aq pejesotte ButyyAzeae sesoTS pue seers qaodmeta s,ueezDs ey OjUT sZOTOD eyQ HutpeoT pue 
* szOTOOU<-uqTT pue ‘eTqeqzoTOD<-uq Ty} ‘bureo<-uqTt ‘pywd<-uqTt 
wqrTtpeotun »/ dn 6utajes ‘xz0s<-wqTt peuedo Apeexzte aznoXk ojuy WATI we peoT TTT 
‘@eUeUSeTTS pue ‘OFUIWNAII POZTTIETITUT ue ‘OTPUeHAAI esn-ut—-jou e& pessed 


o"wiq|Ipeo|/Sejnpow o°wiqjipeo|/Sejnpow 


RKRK KKK KKK KKK KKK 





Source Code 537 


IFF Specification 


{ 

{ (eztsaqnd) wrnjez 

‘qsep = qseqd, 

Jeoznos = eornosgdy 
{ 
fyeezq / (pase T ‘qzeQsz-jJnqu)unyANO -NNU eseo 
‘yeezq /(gynqu)dumaq3no :annd eseo 

} (epou) qo3ztas 


{ 


fo = o4seT 


f, yeerq : 
{ 
‘avnd = epow 
‘oO = 3zeqsz ‘T = jFnqu 
72 = fo] enq 
2 (ogseT ‘Q7eQ8z7-T-JnqQu) UNYANO 
/« unz qndqno ,/ 
} ((anuxew < qreqsz-gnqu ) || (>3seT =i 5) ) FF = NNY esd 


iyeezq 
/x WI JO ASITT »/ /T-ynqu = 4z7eQsr este 
{ 
/-"Unzr e Z esoyy Bbuyyeu Aq esoT 3,ued os 
‘ssexBbord ut dump ou ,/ ‘NOU = epou 
(0 == 92B382z) JT ESTO 
{ 
‘NOU = epou 
/(aze382)dumqqno (0 < 3278382) ZT 
} (unguTW =< 97eQs82-znqu) FT 
} (pasetT == 9) 


{ 
/yeezq 
‘0 = qreqsz ‘TI = gnqu 
to = [o]3nq 
! (t-3nqu) dama3no 
} (aeaxen<gnqu) JF 
/*» e3ep eyQ weqQ 
‘eqkq yqbueT eyQ SEATIM ‘TINZ sy TEFZNG CUR FI ¥/ 
:dNnd eseo 
} (epow) qo3zTas 
‘()eqMaqep = 5 = [+4+3nqu] snq 
} (@ztsgmoz-- ‘feztgmozxr /) xz0ZF 


2-Jay0ed/Sa|npow 


/x° w8zee @34q euo eoutTs »/ i--ezTSsMozr ‘TI = yuqu 

/» D3SPT pTTeA eaey os y/ /()eqhaqe9 = © = O3seT = [0] 3nq 
‘o = eztgqnd 

‘qseqd, = 3sep 

feoaznogdy, = epznos 


/* 83ze4S UNT QueTINS xepuT rzesznq »/ 49 = qreqsz Ar0Y4s 
/* XeFFNQ UT sTeyo Fo zequmu x/ ‘Qo = yNnqu 3z0YNs 
‘and = epou To0E 
1,0\. = 238eT’o zeyo 
‘q8ep, ‘eornos, FLAG 
} 
(@ZTSMOT ONOT ‘380eddy, ALAA ‘eoanogdy, ALAA) moTyxDed ONOT 
/s 
*seqkiq pexyoed so Qunoo snunLau “sxrequtod uofjeutqsep 


pue eornos ey Sayaerde ‘moz ouo syoed ‘SUALNIOd OL SUBLNIOd weatS »/ 
mozyoed -----------4/ 


‘uu ‘Qsep) unyaqng qsep (do‘uu)unyaNnoO euTyepH 
(uu ‘qsep) dumaang 3s5e9p (uu) dumq3jno eutyzep# 


{ 
/ (qsep) urn jez 
(pd) oqAggnag 
 ((t-uu) -) 094qana 
quy /qsepy ALAM (00 ‘uu ‘Qsep)UNyaNdy aALAG OF3eIs 


{ 

/ (qsep) uznqez 

‘ ([¥] nq) e34qana (+47 ‘ua > F /0 = F)z0z 
 (T-uu) eq4qqng 


?F 3uUT 
tau 3ut /3sep, GLXG (uu ‘Qsep)dumajnd,s BLA OF3e3s 


{ feztsgnd++ (5) = ++380p, } (>) e3hqqng eutzopH 
(++002N0S,) ()eqgqep eutsep# 


/xd4OUAS UO EBZT OG pTNoYs [dab] x/ ‘[9sz]znuq rey oTWeQs 
feztsand SNOT OT3eR5 

/* 

*wezbozd aznok ut sq0efqo peuweu-ouwes yQtmM SupAofyuoD worzz ‘oeTNpou » 
Sty Uy peouezeszez ATuo eze yoTYyM ‘seueu eseyy sdeoy stun + 
‘eqeatid sueeu oTqQeqs ‘suotTatuTsep TeqoTS uo pesn ueyM »+/ 


8ZT WeaxeW SuTIOpH 
8ZT UNYXEN SUTFOPH 
€ uNnYUTW euTsepH 


T NOU eutzep# 
° avnd eutsep# 


uy zeyoed/dzzF,, Opntout# 

*zeqnduos ebywy-ezopoumop eyy TOF uoTszreA BTUL x 

“ dOON 82T- 

‘seultT3Z I[+(u-) peqeedez eq 03 e7hq Aq pemoTTos {ezt-"*T-] 
‘eqep zo seqkq T+u Aq pemoTTos {uet"°o] 
:seqhq [TorqQU0D 


‘utTeuop oftqnd ey ut st ereMgzos sTyUL 
‘sqzv oTuozQ0eTa ‘MeYS enegjS pue uostTII0OW Arzec Ag 


KKK KKK KK 


* 


$8/ST/TT ‘uotssezduop unz ,TunyezAgdum, 03 eQep 3zreAU0D D*zexXOed = 
Se, 


0°4040ed0/Seinpoul 





vices 


De 


538 ROM Kernel Reference Manual 





pt ‘edX3_ Fo sXezze pzombuot peqeuture; @Nod OWL pue 
“(W@II GI extT) Prdnoz6 ‘ (yniod aI extT) edAqdnozb x 
‘eTpueyadI uedo pue peztTeTAyUT we 4AM OCFUleszeg & poessed » 





* 
eTtzteszed x/ 





‘TION = peuedo<-td 
TION = preogdtTo<-td 
‘TION = weez3s 334<-33T 


= { 
‘((weexas F34<-F34) (x ATIA)) Osotos 
este 
/ ((mreezas Z3T<-F5T) (x OTPUEHATTD JonzTAs) ) precqdtTOeseTO 
(preoqdt To<-tTd) a 
= (weez3S J3T<-35T) FT 
{((weezas FFT<-FFT ‘nPTTFn 2 upreoqdyTo, ~ preoqdtto<-td 
‘,U\ZTSgsureerys ‘sz esOTS 03 QnoGY :eTTSTesOTO,,) nq) aq 





(peuedo<-td) st 





2 (JFF) AIIOSOTO 





£( (peuedo<-td ‘33T 
‘,U\PTg=peuedo ‘xTeg=33t ‘uedo JF JATOSOTD OF JNogqy :eTTFTesCTD,,) nq) aq 


fuznqez ((333<-Fd=35T) i) IF 
fumnqez (tdi) 37 





1 ((nt\ OT FZ FESOTO,,) bnq) a 
?33%% SOTPUCHAII JORIS 

} 
(Fdy oFUlesrTeg JONAS) STTFFESOTO pTtoa 


/* 





* 
*syunygo pezeq3eb no yoreq eATIM * 
pue AzTpom of eTqe eq TITAS pue eTTFTESOTO ued nok yeqR os pezeyzed x 
sey oszedszyt syunyo eyy euoTO noA MOTTE YOTYM soutTynor roy ETNpow » 
p*syunyotdos ey3 9eg “Ano yORq sehueqD eATIM 02 ETT eyA uedoexr * 
02 ystm nok ‘etduexe 20x ‘JT SETTFTESOTSD OF peeu osTe nox *(,[u]5-,) * 
pzeoqdt{To Bbutsn st eTqtssod se woos se SETTFFESOTO pTNoYs NOX — SION » 
* 
‘eTtsteszed Aq peszed qxequoD eszedzzy} ” 
Tre seezzy pue ‘etTtsyTuedo yaTM peuedo pxreogdt{TD XO ETTF sesOTS » 
* 
STTFIOSOTO */ 








/ (z0zze) uznAQezr 
xozze aaruedo,) 5nq)a 





/ ((z0zz08’,, U\PT% = 





/s © Tpueq uedo ATQuezInD ,/ ‘gouL : 3STWd & rt0zze = peuedo<-Td 





‘(epounedoszt ‘33 T) AAIUedQ=r0z70 


JeweueTTy = eueue[ts<-Ttd 










pzeogo ‘,u\ :peuedo eTtz s%,,) Snq)a 


{ 
PEM STE naa ato esTe 


‘((eweueTtz =: .[preoqdtto], < 








0°asied/Seinpow 


‘ (@TIAON) wznyjez 
/ (eureueTTtz’,,u\*petTtesz uedo ett” :s%,,) obesseu 
} 
((([T 3 epouuedozzy] sepouo ‘oureueT tz) uedoz 
(ONOTO) = weez3s F3T<-33T)i) FF 
/* 
‘O/I Ofp3s pezesznq zoF eTpueHAAI dn Aes » 
a/ 
‘asTwa = pzeoqdtTo<-td 
} 


{ 
2 (337) Saar 
+ (ATIGON) wznQez 
{(ayun’,u\"pettes pts 3Fun Jo uedo pzeoqdtTo,,) ebesseu 


} 
(((ayun) preoqdyTouedo (SNOTA) _ 

= weerys J3t<-35T) i) 3T 
‘gnaL = pzeoqdtto<-td 

/* 

"O/I pxreoqdtTIo roy eTpueHAAI dn 30S » 
a/ 
} 


(pzeoqo) 3T 


‘((z]eweueTtz3) Foye = Qyun ({z]leweueTtz 33 prego) zt 
$(,2, s= [T]eweueTtz 33 ,-, == SWeUETTJS») = PreOogo 


! (dowaad_INATTO) uznqez ((334<-Fd=33F) i) 3F 
! (2owaa “LNAITO) uzngez (di) FF 


= {zozze SNOT 
‘aITO AWWWIUd = Fun = ONOTOA 
ipzeoqo ‘T008 
735TH STpueK_aAT 3ONT3As 
} 
(epoumedoszt ONOIN ‘eweueTtzy ALAGN ‘Ttdy osuIeszeg AonrAs) eTTFTUedO ONOT 


/* 
(y‘eszedgzzT/seTzerqy{) WUETAI we TO sseDons OJ O suINzeY » 


Yaya esn roxy pxzeogdTTO zo eTTF suedo (aLIUM adaI JO GvaN AddI) = x 


* 
ettstuedo »/ 


‘{oMu‘nn} = [Z] sepouoy aLxaa 

2 (4 pupweezysaaI qOonz4s ’y OTPUeHTII 2ONTAS ‘y YOoH yONTAS)WeeTAs OTPIS ONOT 
/x* sedXj030z7d uozAounzZ TeDoT »/ 

nU'FFT/ATTF» OPNTOUTH 

<q" sedXi3/oexe> epnTout# 

/* 

(0 aTReEZep) “93 TO- OD- UT se ZTUND- ZO D- sy pxeoqdT{O TOF eueueTTZ SUL x 
qemyos oey Aq d*TYOoT Fo euos uo peseq e 


etnpou yzoddns or eTtF eszedzzt - o°eszed , 
«/ 


o°9sieq/S3jnpow 





: Source Code 539 


IFF Specification 


{ 
{[ = atnsez ((pt == GI uo<-uo) 99 (edAq == edXy uo<-uo))3T 
} 

(( (ud) yunyoquezed) = uo) ZT 

} 


(((3J3F) AUnyOQueTznD) = ud) ZT 


‘Oo = 31nsez SNOT 
IUD» SPONAXEQUOD QoONTAS reAsTbez 


} 


(PT SNOT ‘edAQ ONOT ‘F3Tx STPUBHAII FONTS) sStqZxXeQUOD ONOT 


(WHII QI ®ATT) AUNYo Quezzrno eyR Fo yxeQuoD HutsoToue eyA suinqer » 


STAxXxeQUOD ,/ 


/ (aTusez) uznqez 
oe ss { 
3Insez ((pt == GI uo<-uo) 99 (edAq == edXy uo<-uod)) zt 
} 

((33%) AanyOJueTInD = uo) FF 


‘0 = 3Tnsex SNOT 
JUDd»% SPONRXEQUOCD WONTAS A0eAsTbez 


} 


(PT SNOT ‘edXkQ ONOT ‘F3Tx STPUECHAAI 3ONTRZS) stXUNYOQUeTINS ONOT 


(QWWO GI SAFI) AUNYD juezzno eyZ Fo aI eyR suanzer x 


sTyAuNyoOquerANd x/ 


= 2 (<<) uznqez 
‘++ (3NOd OWL =i [x] Aezzepebbey) ottyn 


“0 = 4% SNOT 


} 


(Aezzepebbe3, SNOT) 3UOAYS ONOT 


Kezze ut (pt‘ed&q) sxted yunyo zo zequmu ey3 squnos Atduts , 


* 
QUoAYo »/ 


{ 


/ (x0z20) uzN_ez 
‘(33T) qxequooqeb = zozrz0e (x0220j) ZT 


{ 


/x* ®TTZ xeTduoo e st styQ - BHutuzem y/ ‘gna, = quny<-td 


!((ad&ydnozby ‘qr uo<-uoyg ‘edky uo<-uo9 
‘,u\'""S,Sp°% peppeque z0z HutHooT ‘“sy"s'sp's (ule st stuL,) 5nq)a 


} 
(edAgjdnozb =; edXy uo<-uo || ptdnozb =; qr uo<-uo) 3T 


{ 
* (2TIGON) urnqex 
J(,u\ixunyo dog ou /zorze butszeg,) ebessou 


/* 


“ueyorq st zeszed ano 


o-asied/seinpow 


sueou 43T ‘seop 3t JI ‘ueddey zeacu prnoys ATTeer stuL » 


% 
(((334) YUNYOQUeTIND = ud)i) JT 
/* 


‘(WEH'II) Quem am edAtQ Jo wr0F eTduTs JT eos OF OFUT Yunyo yy 3soL » 


«/ 


is 7 (0729) uznAeT 
((43LS JsewdsdI ‘FFT) AAIesreq = ToT) ZT 
/x 
‘yunyo uteu zeque 09 deqs eszed y4satz exeL x 


x/ 


/ (z0zze) uzNASeT 
((ptdnozB ‘edAqdnoz6 ‘33T) atxguodojs = zozze) JT 
(edXqdnozb) 3T 
/* 
*qxequo> WHII ue Fo pue ey We doqs of QUEM OM » 
a/ 


?(zozze) urznqez 
(((syqyodoys) quoyyo ‘sxyodogs ‘334) syunyodogs = zozz9) ZF 
(syyodogs) ZT 
/(zozze) umnjez 
(((sxYDQDeTTOD) qUDAYO ‘syxYoRoSTTOO ‘FFT) syUNYQuoTIOeET TOD 
= z0zx9e) JT 
(SYYOROSTTOD) FT 
/(zozze) urn zez 
(((sxyodozrd) quoyyo ‘sxyodozd ‘334) sxunyodozg = zozze) JT 
(syyodord) 31 
* 
“*syunyo dogs pue uotqoeTToo ‘Aqzedozd gvoaa 


»/ 
‘asTwd = quny<-td 


‘(waa wasaaaI) vanqez (weez3s JFT<-FFTi)IT 


‘(doMAT INATTO) urnqez ((334<-Td=33F) i) Ft 


/Jo = zozze SNOT 

LUD» SPONAXEQUOD AONzAs z0eQ4sTbez 

‘33Tx STPUBHAII ZONTAS 

} 

isxyodoqs, ‘syyo Roe TTOo, ‘syxyodordy ONOT 

fedxqdnoz6 ‘ptdnoz6 snot 

itd, ogureszeg  3onz4s 

(sxyodo js ‘sxyoqoeT ToD ‘sxyodord ‘edXadnoz6 ‘ptdnoz6 ‘td) ettzteszed SNOT 


/* 


(y*eszedzzT/seTzerzqTT) WHAdII pue esTe sseDons ToJZ OQ surnyzeYy 


*pezey eb eaey nok ejep eyQ 

eqtimez pue Aztpou Atduts oq Aqtrtqedeo eyq eaey jou Aeuw nok 

qeyq nok 03 Teubts e eq prnoys sty, “368 eq TTT Betz yjuny<-td 

ey ‘WAOd peaztsep znok putz oj WeEwTOZ xeTduoD e OQUT eATEp OF sey 

(jettzxTeszed JI “STTF aa eures eyQ Hbutszed enutquod o3 ystm nok ZT 

(@ETTF owes oyQ ut wrogz Axou oszed of ‘DOE WUAAAI r0EQTZe) () xeEQUODQxXEU 
zo (yunyo dogs e zeqze enutTquoD 03) ()3xequonqeb [Teo ued noX - a30N 


‘yunys petztoeds uo 

Sbutddoqs pue butzeyzeb/butqqerz6 ‘eTtF aaI ue_eszed TIT 
({ 3Nod OWL ‘SWWOD GI ‘WWII GI ‘GHWa GI ‘WHTI GI } ®xXtT) 
uo peddoqjs pue ‘pezeyjeb ‘peqqez6 eq of syunyo TOF 


o°esJed/s3aijnpow 


RE KR KR KK KKK KK KE KK 





Devices 


540 ROM Kernel Reference Manual 


*Kazqugyoow (() (x) ONOTA) 

‘{ ‘TION } 
WYooRH Wonazags OF RQeRS 
ONOT uzr98qxe 


} = yooyotpys 
4 () Axquayoog 
} 

‘3F}% OTPUeHAII AourAs 
(FFF) CFPASSEFTTITUT PTOA 

/* 


eaoge TeTpueY weer4s ETTF SYR TOF YOeQTTeo yooy dn sjes » 
(OFP3s se FFF ATUT “OT) OTPISseTTTIATUT af 
{ 

#(0), uzngez 


/x ‘pexztnbex aONVHID ZO LINI ON +/ 
:ATnezep 


f(0 2 Mus WagaarI ¢ (T- == (1 ‘seqdqu ‘uweezqs) yooss)) uznqez 


(TenQoe = 


(TenQoe 


‘Mgg9S OOSHAII ese 


(0 : GLIUM WugaaI 2 seqhqu) uznqjez 
‘(0 < seqXqu) ettym { 

iqvenqoe =+ jnq 

fTenqoe =- se qfiqu 

syeerzq 
i ((Qweezqs ‘TenQoe ’T ‘3nq) EATAMy=ueT)) FT 
fseqhqu : Louze & LoLze < seghqu = TenQ0e ; 

op 


*GLIYM OOSHAII Ese 


'( 0 : quae wagaar ¢ seqXqu) urnjexz 
(0 < seqkqu) ettym { 
iqvenqoe =+ jnq 
/Tenqoe =- seqAqu 
fyeezq 
=j ((weerqs ‘TenQo0e ’T ‘ynq) peezrz=ueT)) JT 
fseqkqu : 1.9Lze & LOLZE < seqdqu = TenQoe 
} op 
is tdwaa OosadI seo 
} (pueum0g os<-3yduoTQ0B) yo uTMS 


igng@ os<-qyduoyzqoe (x ALGO) 
fseqkgn os<-qyduotqQo0e 


= gnq 
= se qiqu 

_ ‘(t)urnqez (weez3sj) FT 
fweez3s J3T<-F3T (x ATId) = weerys 


/ueTt Huot 
‘3nqy GLAGQ r9AsTbez 
iTenqoe Aut zeqstbexz 
{se qiqu NOT 10Q8T5er 
fureexysy airld zeqstTbex 
} 
‘qyduozqoey pupueez3sddI oOnzys 
Prats STPUeHAAI 3OnT38 
JYoous YyooH Aonz4s 
(ayduofqoe ‘337 ‘Yooy) weez4s oTpIs 
ONOT OF3e95 
* 
use‘ 7ZOOH pue YOOH WoONIAS STA SpoOd sty Q STTeo Foes 


+ (Z0zz@ ou) sseDoDNs seQeEoTpUT Oo FO urNIeT YW 
“TTBS TItM AeIQTT gal SYR YOTYM suOTZOUNZ Yooy O/I TTA 


9°esied/Sejnpow 


{ 


= ‘ (9) uanqez 
/(eqeq ds<-ds)uznqez ((pt ‘edAq ‘z34) dozaputga = ds)3t 


‘ds, Kqzedozgapez0jg 3onz4s zeq4sTbex 
} 
‘pt ‘edkq SNOT 
tJTT* SOTPUBHAAI yonzAS 
(pt ‘edk3 ‘334) e3epdozdputzy gLAGO 
/x 


(punogz jou xox 9 x0) eqeq ds sqy 03 xrequtTod surnjer =, 
pue ‘eTTsZ JAI worsy peszed yunyo petytoeds sputy » 


* 
eqepdozdputy x/ 


/ (x0zze) uznAeZ 
/((,u\deqs qxeu yqbnozyQ 30D :4xeqQUCDRxeHU,,) bnq) 
‘(@9LS BSUWaadl ‘FF4)aaIOsTed = Torre 


{79 = 10226 SNOT 
} 
3FTx STPUCHAII  Aonz3s 
(FFF) FxOQUODQxXEU ONOT 


as /* 
(@eTTF FO pus) JOA WAAAAI se yous waIMII we To O suznqey * 


‘Qt eszed pue 
STF S42 UT peuTequon 4xeqUOD 4xeU 9YQ TEQUe TTTM JxXeQUODRXEU 
“(00% WaAAIAI) 3xeQuod znok Hutpeez pue SHutszed peystuyz eaey nok ZI 


qxequooqxeu 


‘((NWOS SsuwaddI ‘F3T)dgIeszeq = Torre) urnzez 
= /* 
= (40a WATT = TOITE) SETTF FO pue TO » 
(D0a WagddI = Tore) WAOA WATI ue TOF yxXeE QUOD JO pue TO » 
(9 = zozze) yunyo dogs e uo uiznjez TIT ()aFirTested « 
‘UOCTREZTTETATUT eszed ano uo peseg x/ 


279 = zozzx© SNOT 
} 
fJ3FFx STPUCHAAI  JoONTAS 
(334) axeQU00R05 ONOT 
Ss /* 
(@TTF FO pue) JOA UAAAI TO 
(zozz= ue jou ‘AxeQU0D Fo pue) DO UWAAII I 
(xunyo doqs e uo peddoqs) 9 surnqey 


JOU 2O ‘QxeqQu0D Jo pue zo ‘yunyo doqs petyztoeds qe Hutddoys 
‘()ettzteszed 09 petztoeds sem yotym 3xequop eyR zeyqeb oj senutquop 


* 
* 
* 
* 
* 
* 


() 9xeQU00905 y/ 


/ (9TNsez) uanqez 


!((ar wo<-u9 ‘edAy wo<-u09‘,,u\sp"s sy°% B ST STUL.) Snq)a 


9°esied/Sejnpow 





: Source Code 541 


IFF Specification 


{ 
/ (x02zZ@) UIN_eT 
{ 
/ ((zozze’,,u\pT% = xozze - yunyodog zeqgzw :499Nd,,) 5nq)a 
£(334) HunYoOdog = zoxzze este 
= { 
‘LITEM WAAIII = xrOxzIEe 
/((aeTs/ezts‘,,U\pTs ©302M ‘PTZ = EZTsS :rorzre seyAqyunyoe3tsM,,) 5nq)a 
} 
(ezts =j ((ezts ‘eqep ZZ) seqAGyUNYOSEITIM = WETM)) FT 
/s B3ep TeNAe ey Q SQTIM x/ 


{((zozze ‘py9‘,U\PTs = zorzz@ ‘sy's FO YUNYOYSNg :yx93nNd,,) fnq)a 
} 
este 
{ 
!((py ‘(zozze)zzeag1 ‘PT 
‘,U\PTS = ©zts ‘8% = zozze ‘sy*s% Jo yUNYOYsna apseanyOndia 
((ezts ‘PT ‘Oo ‘¥FT) HUNGOYSng=r0770) ZF 


‘((0z78 ‘PT ‘PTe’.U\pTs wybueT (xTs$) .\sp°s.\ AURGO ysnd of pexse :yO3nNd,) Snq)a 


‘aeTa ‘9 = zozze Huot 


} 


see ges 
/(z0zze',PT% xr0zrze esti ‘uuseqtaye ote 
rabasey ae 
Ltdeesoeaeae 
(JTIAON = sosaeig 
“ine tedy dsnaae 
(4owas INEITO = austere 
(It - (auss0) ipheciss tel Mawins 
(o > seas} 37 


1,2dkq Buorm ro punoz jou eTTdn {]©T#you aALAGN OFWeQS 
fyZOIZTS AUETTO. {]3ueTT> aLzGn OF3Qe9R8 
‘[ze]umouyun aLzGn te 
wu QUGTTS OF UINIeU, 
‘, ‘Bbutsstu zoq0ea yooy peaztnbey,, 
‘wOTTF ddI ue JON, 
“zozze xequds gar, 
‘,°qduzzop st eTTd, 
‘,°Zozze yoos weexz4js, 
‘,°ZOIZS SATIM wee2»xjsS,, 
»"XOITS peer weexsjs,, 
‘, ‘Azowew quepfotzsznsur,, 
4, °edops TeOTXeET ON, 
‘,* (xoxz@ we jou) AxeQUOD Fo pug, 
‘,° (zozze we Jou) STTF FO pug, 
} = [])sbsuzozze, aLAGN CFWeRQ8 
* 
‘tT - 20II9e- = XpPt fe 
"euo AoerQqQns pue ‘47 eqQebeu ‘epoo 
wagaaI xmn0oX eyeq ‘Aezze stqq ojuy xeput eyQ AeH oL ‘“seutqnoz gar 
SNOFIEA WOTF surn_eT ¢# WITAGI ETQTssod rox sehesseu xzorzze yst {bug 





izozze SNOT 
(z0zz0) 7zegIIx ALAGN 

/* 

(zozze ou) TION x0 Buyz4s8 z0zT7g adI OF TeQUTOd surnjQey » 
* 

TZTOGII 


»/ 


/(yooyotpass ‘Naas Addl | WAIST aaa ‘FFT) AAIIFUI 
/* 
‘mots Atqyazzr98ey st O/I pezezsnquyn ‘“seutyAnox » 


vices 


: De 


(e2epx ptoa ‘ezts Huot ‘py Huot ‘FFT STPUBHAAI JONTAS) AOQNa Huot O/I pezezgnq eyy OF AuTod of eANQONzAS FIJI SYR SOZTTETAFUL » 
/s 


* 


eTpueyszT ue 03 BQep FO YUNYD euo seRTIM » 
TION 


* _ 
yMOand » ‘weez3s OFP3s (() (x) ONOTA) 


o°9s1ed/s3i/npow 


o°9s1eq/S3a/npowW 





542 ROM Kernel Reference Manual. 





((SWwO GI =i aryunyS) 99 (a¥ND GI =i arxuny>) 33 (HWE GI =j aryunyo))sT 
ns far qo<-yunYyS = qrIyunyo 
!((ar yo<-yungos ‘,,u\sp's & eaey - T3STTHUNYGDS,,) nq) a 
a } 

(QxeN YO<-yuUNYS = yuUNYS /yuNnYD /TAsTTyXUNYO = yunyo) rox 

/x 

(XTeqezedes ue q3trM/peqnduos) oWWwO 20 ‘dwWo ‘GHWa Aue , 

zoz 3deoxe ‘(Aue ZT) Z 3 T SAsSTTAUNYS Qno O4TIM x/ 









/((zozze',,u\pT3 = Tozze - OWWO ‘dWNO ‘GHWagnd 3seq,,)6nq)q 


‘ ((pyepous ‘zz 7) bureognd) z2g49 
/((zozze’,,u\pT% = zozze - bureoqnd ezozeq,,) nq) a 
‘ptepou = Sureo<-wqTt 





(@TTEITOTOD) FF 





! ( (unbreds3tq/szoponu ‘eTqegzoTOo ‘ZZ 7T) deuynd) zzg49 
! ( (puwa<-wqT Fs ‘3FF) pyUqand) 7zzAD 


/((xozze’,,u\ptTs = pyuqaqnd ezoyzeq x0z2zg,,) 6nq)a 





i(pfepou ‘qyhteyebed ‘yqptmebed ‘ayStey ‘qapTA 
4zotTooquezedsuez3 ‘Tunye3Xgduo ‘buyyseu ‘dewjtq ‘pywg<-uwqTty) pywqytut 


/((zoxzze ‘,u\pTs = zozze - WHTI WuOd AUNYYsna 2097 ~,,) 6nq)a 
‘(NMONINA AZISaaI ‘WaOd GI ‘WAII GI ‘337)XUNYOYSna = rorze 


/ ((eueueTTz’,,u\eqTrm roxy s% peuedo,,) Snq)a 
7 } 
(((ALIUM GHAI ‘oweueTty ‘wqTt)eTTsyTuedo = zrozze) j{)FT 


{ 


‘(WEWON WUAEET) uanqez 
/(,u\zouweu ybnoue 3on,,) ebessour 


= } 
(((oTTand AWEW'ZSANAAGOE) WEHPOTTY = FnqApog) i) FT 








((0000a443%0 3 PTEpou) j) FT 





?ASWWONWOTTIO 





=3 ptepouw 
JZ F OFULOSTea<-wqTT = FFF 


960% ZSANGAGOG SUTTEPH 

‘79 = zozze ‘ezts SNOT 

iznqXpoqy aLAan 

‘aryunyS SNOTN 

Jyunyd, yanyd 3onaz4s 

‘33T% STPUCHAII JONTAS 

} 
(eweueTT3I¥ FLAN 
‘ZaSTTAUNYSs YUNYD AonzyAs ‘TAsTTHUNYo, YyuUnYD Jonzys 
‘xoTopquezedsuez3 quom ‘butysew qaom 
‘unbreds3tq GaoMnN ‘sroTODU GYOMN ‘SETIeITOTOO ULdW 
‘gybreyebed quom ‘yaptMebed auom ‘ayStey aaom ‘YaPTM GUOM 
‘pfepou ONOTO ‘deurntq, dewata qonzqs 

‘UqT}* OJUINETI JONT3s)uqTTeAes omer 

* 

WAAIII we TO ‘sseoons A0F Oo surznqey 


Ayeqezedes ueq4Tazm pue pezeTnoTes ere AeyQ esneseq 
(qno peueezos eq T1T™ Aeq3) OWWO pUe ‘a¥ND ‘CHWa wey, zey}0 
weqQTzmM ystm noA syunyo rOF st ASTTAUNYSy, YUNYD RonIAs eyL 


uu se peaes eq TTTM u sunb 3tq rnNOW 


*@WWD OF WEqATIM eq TTT* und yoee Fo satq aqSte ySty eyq ATuo 
‘pqe qouasu zo sun6 ONOIN st eTqezroTOD ‘ze=unbreds3tq ZT 


2 Wg|leAes/Sejnpow 


Re K KKK KKK 


‘g=unbzedsqtq 5T 


(QWWO © EXTT) “930 aOyaSU Fo sunb e3Xq st eTqeQroTOo 
‘py=unbzedsqtq ZT 


GOYO SETAQTU YATM YoRe ‘spIOM ST ETQEQTOTOD 


“"WHII ue se deuwytq eyQ eAaesS TITH 
‘eueueTts pue ‘sqstTyunyo Teuotqdo ‘zoToo quezedsuezy3 ‘butysew 
‘unbzedsatq ‘szoToou ‘eTqeqroToo ‘sqyhtey/suApta ‘ptepou 
‘zqad dewata e& ‘eTpueHadI JF t<-osuIosied 
(@sn-ut-jou) etqetTteae ATquezzno e YRZTM OFUIWATI we useato 


Re KKK KR KKK 


wuqTtTeaes 


* 
~“ 


— / (r0zz9) UTNAEeT 
/WEWON WAIIJI = TOIIS esto 
{ 
2([T >> qunod ‘eTqeqrOTOD) uweyeecelg 
i (eueueTtz ‘ZastTyunyO ‘T3strTyunyo 
‘9 ‘auonysu 
‘y ‘qunoo ‘eTqeqroToo 
‘qyBtey<-z0s ‘q4ptm<-zos ‘qqSyeR<-z0s ‘YApTM<-20s 
‘pyepou ‘dewata<-z9s9 ‘wqTT)wqTfeaes = zo2zz°e 


(+44 Jqunos>yx /oQ=x) r0F 

= } 

((QW9TO GWEN ‘T >> 3uUNOD)WeAOOCTTY(¥ CYOMN) = STABITOTOD) FT 
Squnop<-depyzo[oD * 3TOgMETA<-TOS = QUNOD 


! (x ‘deyzopoo ' 320ameTpA<-705s) panw3eo= [4] eTQeAzoTOD 


SUASWWONWOAGTIO 3 SePOW’ AAOUMETA<-A9sS = PTSpouw 
este 

f (QTOgMeTA<-2083) CIOPONAAI99=PTopour 
(9€ =< UOTSIEeA ATT<-osSegRID) IT 


4 QUty 

{10IZI@ ONOT 

‘PTepou ONO 

fqunos ‘eTqeqyzoTODy dyomMnN 

fesegxgo,y AzrexqtTT WoOnzAs uz09qxXS 

} 
(ouweueTTt3» ALAGN 
“ZaSTTAUNYoO, YyUNYD QonTAS ‘TISFTHUNYS, YUNYD Jonz3s 
‘TOs, weerdsg AoONIzAS 

‘UqTT, OFUINATI 3ONnT4s) eaesusezDsS ONOT 

/* 

(y‘eszedzztT/seTtzexzqtT) WaaddI ue TO ssedons TOF OQ surnzeY 


yseu pue TOTOD Quezedsuezy rosy TION sessed eaesueerDs - &30N 


‘ (ATeqezedes ueq4Tim pue peqnduco eze AsyQ esneseq 
qno peueezos eq TTTH Aey3) OWWD pue ‘dYWD ‘CHW ueYR TeYyqo nO 
ueqayzim ystm nok syunyo z0oz exe Z PUB TASTTHUNYOy YUNYD QonzyAs eys 
WHII we se usezos eves TITM ‘QsTTXUNYD TeuoTqdo 
pue ‘oweueTTz ‘zequtod usezos e ‘eTpueHadI JF T<-osuloszeg 
(esn ut jou) eTqeTteae ATquezznd e& YATM OJFUIWATI we weato 


KEeEK KKK KKK KK 


D° SaAesUseIOS 


* 
~ 


fesegxgo, AzexzqtTT Qonzys uz6e34xe 


wa ddeuqtt/dgz},, epatout# 
oT WQTT/dZFT. SPpNTOUTH 


/* 
seuTQNor eAeSs WATI TeaeT-ubtH » 


* 
Wad zeuddeyos “5 16/SO D°uqTTeAeS »/ 


J W|ieAes/Seinpouw 





: Source Code 543 


IFF Specification 


! ((q6ty ‘opts ‘qqybTeq<-r08<-uqTT ‘YIPTM<-708<-wqTT 
‘,U\PTS X PTS =pessed pie xX PT% =2Z0s :sezts,) 5nq)a 


ixos<-uq{TTt = ueex0S<-AU 

i (muzep9), = AU, OSTS 

! (FOpUya<-uqTT) ~ = MU, (FOpuTM<-uqTT) TF 

JUTMMeUZ = MU 

} 
((epou ‘deep ‘ySty ‘eptm ‘uqtt)ueezosptuedo = 20s<-wqT}t)sT 
‘ (uq tt) Aetdstpesoto 


{AUy ‘UTMMOU MOPUTMMON 2OnT4sS 
} 
(epour SNOTN 
‘deep LuOHS ‘YHtY LYOHS ‘OPT IUOHS 
‘UqT Ts OFUINATI 20onz3s)AeTdstpuedoy moputmM jonz35 


Is 
“TION ZO MOPUTMy SUINASY »~ 


“MoputM pue ueEezos epou _E"T PTO Ue este 
‘MOpuTM puUe uSeezDs GIepow 0O°z 3OeTx0D uedo 03 sydueqWy 


arepou ‘suojtsuceutp ‘osyurwaTI pessed - Xetdstpuedo 


{ 

/x moputm zo edky NaTIOSWOLSND 

/= AUSFOHXeN puUe YIPTMXEW ‘o ‘0 

/* FASTOHUTW PTS YIPTMUTH ‘oz ‘0S 

/x zequtod dewata ‘TIAN 
/* peuedo TIT TIna 13d ueezs 
/« Buyzys STITL 

/» szequtod efewy pue jefpes »/ 2 “TION 

* WALA | ALWAILOW| HSHAITATAVOON | HSTUITE LUYNs | ssaTaaquog | doumiova 

/* soteq sheta uate sheta aWOdI x/ ‘SNOLLNGASNOW | ATAWTTINGA 

/+ WeaAOOTE pue uedTTe ,eq »/ “ES. t= 

/« W6T9H pue TaPTM »/ ‘o ‘o 


/« 25padoz, pue ebpaaset x/ ‘o ‘Oo 
} = auzep MOPUTMMON qoniz3s 


/= MU<-uqT} ut petTddns euou ZT MOpUyTM Mou QTNezZEp x/ 


${o~} = []Aexzeued quomn 
“¢ ‘0 ‘0 ‘8 ‘uqQuoz*’zedoq, (% ALAN) } = Quogezes 299WRxXeEL JoRTAS 


Jasequotatngur, Azexqy¢T qonzAs uzejxe 
Jesegxgd, AzezqyT WonzASs uz0837xe 


i(c+* ‘sbeq ONoIN’s dewrotop qonz3s) sbeL_Torzuopcepta = 00d 
uy ddeuqtt/dgzt,, epntout# 
/* 


‘poumsse st 

Aatttaysuodsez zo AjyTTqetT ou pue ‘ysTI umo aznok Ae st esNn TIV 
“epeu eze seTqueziem ou /,sft se, peptaoazad sy uopAewrosuyT sTtyL 
*peazesez sqybtzx z9eYR0 TIw “szeqnduoo ebfyuy exopoumoa 205 
erem{zos ut pesn oq Aeu uopAewroszuy styR uo peseq seTqeqnoexg 


‘pur ‘ebyury-ezopoumoy o66T ‘686T (2) aubtrAdoD 
»/ 


/* 


TAOOT ‘owepueoso ‘ouepos uo peseq y 
Ketdstq xoz eTnpow ueexos 0°Z - D*ueEETOS »/ 


0°U98919DS/S9/NPpowW 


/ (z0z2e) uznAez 
‘ (zsanaxdog ‘3nqApoq) weyeerg 


{ 
/* OTT 243 pue »/ (WATT) OT TF FOSOTO 
/* WAOT OFZ NO BSOTO »/ 1 ((F3F) xunyodog) zzz49 


/((z0zz0’,,u\pT; = zozze - Apoqand yseq,,) 5nq)q 


‘((zsanaxaog ‘3nqApoq ‘pywg<-wqTts ‘TION ‘dewjtq ‘33+) Apoqjnd) 22449 
/s 
KGOG SYA 3ANO OQTIM x/ 


{ 
= { 
‘((eqeq yo<-yunyo ‘ezts ‘qryunyo ‘334) 43nd) 7zTaAD 
_  ¢((ar yo<-yunyos /,u\sp°3 butaagnd,,) 6nq)q 

fezts yo<-xunyo :_ (eqed Yyo<-yUNYS) veT 7348 

&é NMONINN FZISAAI==9zTS yo<-HuNYS = ae 

((DWWO GI =i aGIyAUNYS) 339(aWWO GI =i GIAUNYS) 99(GHWEA GI =i aIyUNYS)) FF 

/((ar yo<-yunygos ‘,,u\sp"% & eaeq_- Z3STTAUNYD,,) 6nq)aq 

/aI yo<-yUNYS = qryunydS 

} 

(axen Yo<-yuNGo = yunYyo /yunYyo /zZasTTRuNYS = yunyo) ros 


{ 
_ { 
‘((eqeq yo<-yunyo ‘ezts ‘qryunyqo ‘334) AOINd) T7aAD 
_ (lar qo<-yqunyos ‘,u\sp"¢ butgang,) 6nq)q 
fezts yo<-yunyo :_ (eQeq Yyo<-YUNYS) veTIA4s 
é NMONINN @ZISdaI==ezFS Yo<-yunyo = iy 


oWgjleAes/Se|npow 





Devices 


544 ROM Kernel Reference Manual 


7 
_ il 
@Nod SVL 
‘sbeqs<-uqtTt ‘sbeqpessed 
‘dew tqzq<-wqT Ft ‘beqdeuatq 
‘xX0IxI09 ‘epopz0r7a_VWs 
‘Kezzeued ‘sued VS 
‘quogesess ‘quod VWs 
‘OT 34 38<-UqTT ‘OTITL_NWS 
‘aSTWd > FOUL & TlorDsogny<-wqTy ‘TToTsoqny_ws 
‘dt TOP? ‘dt¥toda_ys 
‘deep ‘qadeq_ys 
‘qdtq ‘qubteH_vs 
‘OPTa ‘qaPTM_YS 
‘xu’ sods ‘33°1Vs 
‘xutW’ sods ‘dol _¥s 
‘aOaL ‘putyqed_ws 
‘edX3s<-uqTt ‘edki_ws 
‘epom = ‘arAetdstda ys 
“TION (, UWEEeTOSMON QONnTAs) ) shbe_yucezosguedo(, wees AoNTAs) =rT0s 


!MYONDI OVE : HOW SVL ¢ sheqe<-wqTt =_sbeqpessed 


‘3HONDI OWL : dewata Ys 
& ((aWWEIENonsAD 3 edAys<-wq Tt) 39 (dewgtqrq<-wqTt)) = Seqdewatq 


/((,4\sbezueezoguedo 3due33e 03 ynoqy :onaad.) 5nq)a 

(xutw’ sods ‘xutw’ sods’,u\ptg = Autu<-sods ‘pty = xutux<-sods,,) 5nq)q 
((T+xutW’ dt Top-xxen’ dt top ‘T+xutW dt Top-xxew’ dt Top 
‘xxew' dt top ‘xxew' dt top ‘xutw’ dt top ‘xutw’ dt Top 

‘,U\PTS=3qHTey PTS=GaPTM “""PTS’PTS 02 PTs‘PTs dttop S5atsn,)bnq)a 


ot 


! (ddqqon ‘oxeuws ‘opys3 '09x99 ‘dt Tops ‘sodsy ‘ybty ‘eptm) yFdtTO 


‘TTaN = ddtTon esto 
édttonys = ddtton 
(((ed&adzton<-mq Tt ‘dt Ton ‘epow) uepszeaghzend) 93 (edad; ToOn<-wqT Tt) ) FT 
‘ogaIA NWwOSO = edAadzTon<-uqrTt (ceptA<-wqTt) FF 
/« 34¥ Osn ‘oTQeTTeAe pue petstToeds edAq dtTo zesn FI +/ 
} 


(meukz3) 3F 


/((, weezoguedg pto Butop ‘0°Z ION : 
,sbezuecexosuedg buthzq ‘eTqeTyeae epow pue 0°Z =< sI, g MmeuAzQ 
‘,U\'S% 2NHd0.) 5nq)a 
‘ ( (epou ‘deep ‘q6tyq ‘apts 
‘,U\XT80%X0=9pou ‘PTS=P ‘PT$=4 ‘PT¢=m -WA'TIIU\,) S5nq)a 


=o { 
‘ ((CKUN NWOSO ‘oxeurs ‘epour) ueoszeaochzend) 
33 ((GaWaNWLS NWDSO ‘op3s3 ‘epow) weoszeachz0nd) 
33((LXEL NWOSO/03x 39 ‘epou) ueoszreacXzend) ) =meuAzQ esto 
fgstwa = meukzQq (xozze) Zt 


{ 
! ( (z0zz20 ‘epou’ ,U\ > PTS=STIETTEAYIONSPOH XT80%$.,) nq) a 


/ (@epourl) OTCETTFEAYIONSpOH = TOrTTEe 

/ (deep ‘qbtq ‘epta ‘epou) yORqTTeFJepow = epour 

/« epom yoreq [Tey AxQ ‘eTqeTTeae jou ZF x/ 

{((z0zze ‘epour’, a\:pT%=T0ITS ‘eTQeTFeEae Jou XTEOs$ ene 
( (@pou) oTQETTEAYIONSpPOW = TOTTE) FT 
/* STQRTFeAR st Spou ZT Ces ‘9EA =< FT asf 


(((9€ =< UOTSsIeEA ATT<- (esequotatnjzur(, AzerqyI ONT4s) )) 
33(9€ =< UOTSIEA QTT<-(esegxso(, AxzerqyT JOnT3s)))) = moukzQ) FT 


3°U9919NS/S8INDOwW 


‘T3224 8«‘TOOd 

‘sheqpessed ‘Seqdeuwatq SONOTN 
‘meukzQq ‘zozrze SNOT 

‘TION = TOSy uweerDg 3ONnz48 
iddyton, eThueqoey 3onz4s 


» seTbueqoex Ketdstp ./ ‘dtton ‘oxew ‘opas ‘09x 3 ‘dtTop ‘sods eTbueqoey jonz348 


{SU WESTDSMEN AONE 


} 


/x weexzoguedog eTAAs pTo r0F »x/ 


(epour ONOTA 
‘deep LYOHS ‘YSTY LUOHS ‘OPT™ LYOHS 


‘UqTT, OFJUIWAII 2ONTQs) useceroOsptuedo, ueerg joONTAs 


/x 


“TION 10 wesrdsy, sUIN_eY 


“qsftTbeq eyQ Fo pue 

ey3 03 peppe eq TTTM sheq eseyR ‘TIQN-uow st sheQjs<-uqTt ZI 
*deugqtq s,ueezos ey se pesn 

eq TTts deurytqzq<-wqT} ‘a¥ALIENoLsaD sepntouy edAys<-uqT}t 31 


*ueezDs epoul E"T PTO esTS 
‘szezd 6 ,zesn uo peseq uedszeAo 
pezeques Y3TM weerDs GrIepou 0°Z WoerTTOD uedo 09 sy4due jay 


alepow ‘suotsueuwtp ‘osUINMTII - weezosptuedo 


{ 

fTton = dam<-uq{t = dis<-uqtt 

‘7TON = da<-uqTt 

zos<-uqTt ‘(ZOs<-uq[TT)UeEeZDses0TD §(rOs<-wqTT) JT 

UTM<-UqTT ‘(UTM<-UqTT)MOPUTMESOTO == (UTM<-UIqTT) a 
vet 


(WqTT* OFUIWMATI JonzA6)AeTdstpesolTS ptoa 


{ 
? (UtM<-uUqTT) Uzn_eT 
{ 

2 4LOTU<-UTM<-UqTT dim<-uqtTt 
J420dg48PY<-1TOs<-uqT Tt? dzs<-wqtt 
/qrogmeTA<-IOS<-WqT TS da<-wqTt 

} 
(z08<-UqTT) JF 


{ 


/* PET Tez moputmuedo x7 AeTdstpesotTo Aq yno peTInu »/ 


{ 
‘asTwa = ©3e3SaL<-wqTT 
‘(asIwa ‘2z0s<-wqtTt) ee 
(aouaqnowa 9 shel a<-upa<-wqTt) st 
} 
este 
{ 
/((,'mopuza uedo 03 peTteg,) 5nq)q 
! (uqTt) AetdstpesolTo 
} 
uyM<-wqTt) i) FF 
aybTeq<-au 
YIP TM<-MU 


(( (au) Moputmdedo = 
fybty = 
JepTa = 


0°U99J9S/S3/NPOW 


* 


* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 





: Source Code 545 


IFF Specification 


! ((xxen<-dt Top ‘xxen<-dt Top ‘xuTN<-dt Top ‘xuyw<-dt Top 
4, U\PT3=4xeu pTz=xxeu pTz=Auu pTg=xuu : aon.) Snq)a 


/KuypR<-dtton = xutW<-sods 
/yxutR<-dttTon = xutw<-sods 
idytony = dt Tops 
} 

(dtqon) FF 


‘ ( (qxeu‘mxeur/xxeW<-oxeU ‘XxXeW<-—Oxeul ‘UT W<-OXeU ‘KU TW<-OxXeu 
‘,U\PTS=UxeU PTe=axeu pTs=Axm pTg=xxu pTz=AuN pTy=xM : OXY.) 5nq) qd 
! ((upas ‘mpas ‘AxeN<-opys ‘XXEN<-Op3s ‘KUTW<-OP3s ’KUTH<-Op3s 
‘,U\PTS=UP3s PTe=Mpas pTs=Axw pTg=xxu prTey=Aum pTe=xuu ‘:odis.,) 5nq)a 
£ (((9%9/M 9X2 AXCW<-09XQ /KXEW<-OFXQ ’RUTW<-0FX2 /KUTN<-09X3 
‘,U\PTS=UP3s PT¢=Mpa3s pis=Axu pTg=xxu pre=Auu pTsy=xuw :OLXL.) 5nq)a 


{ 
/((.t\opas st dtTo qseq,,) Snq)q 


‘qpas 
‘ap ys 
/op3s 


‘((nt\09x3 st dtTo 3seq,) 5nq)q 


749x9 = YQseq 
/AqXQ = MQseq 
f03xq = O4seq 
} 
((q9x3 => yStyq) 93 (m9xQ => EPTM)) IT 


i T AUTN<-Oxeu AxXeON<-OxXeuU 
‘tT XUfN<-oOxew XxXeN<-Oxeur 
!T + AUTW<-op3s - AXEW<-opqs 
fT + XUTN<-opa3s - XxXeW<-Op3s 
{T+ RUTW<-09x3 - AXEW<-09K9 = 49XR 
!T + XUTH<-09x9 - XXEW<-09%9 = M9xXQ 
/« s3qSyey pue syapyTM xew pue pays ‘3x3 S43 30H ¥/ 


yxeur 
mxeur 
yplas 
Mp 5s 


‘aqseq ‘mqseq ‘yxeu ‘mxew ‘ypjs ‘mpgs ‘3x3 ‘M3X3 8 LUYOHS 
‘KAxzeu ‘Auyw ‘xxew ‘xutuw Laous 
foqseq, eThueqoey yonzys 
} 
(dyqjon, eTbueqoey jonz4s ‘oxew, eTbueqoey jonz4s 
‘opas, eTbueqoey Aonz3s ‘03x39, eThHueqoey Aonz35 
‘dtjTop, eTbueqoey qonzqs ‘sods, eThueqoey Aonzys 
‘ySty LYOHS ‘OPTM LYOHS) ATdTTO ptoa 
/* 
“peeqsut pesn st dtTo 3eyQ ‘pessed st dtton TTnu-uou e JI x 
‘dn peaow eq TTT ‘dog ueoso * 
4xeQ MoTeq st doq zTeuy 3eYQ Yons ASeQUED YOTYM sueeTDS * 
“sQtwTT weosoxeu TebeT oj peutzuoD dtTOp yQte * 


/ (epoumoeu) uznqez 
/ ( (epour‘epoumeu ‘,,u\xTSOsx0 FO peeqsut xTsosxo AzL,,)Snq)a 


‘ISWW GI 3d0W 3 epou = epoumeu 


9°U9e10S/Sainpoul 


*uotjeottdde znoX so speeu oTztoeds eyQ uo peseq 

epow etTqeqtns e z0oz eseqejep Aertdstp eyQ yorees prnoys 
*sepou ezngny rox ptTeaut ATTe_,0q eq Aew pue 

uedo Ketdstp Fo puty euos 306 03 Aem deeyo e jsnf st styL 

*"sqtq epou pro anq BbutyyAzeae Ano syseu Atduts ‘mou z0¥g 


/epoumeu SNOTN 
} 
(deep LuoHS ‘YStyY LIOHS ‘OPT™ LYONS ‘pou ONOTN) XOeqTTeFepou ONOIMN 


(SLTMGSTWH WALXA|WWHISSUIH| OWI) ASWW GI AaoW euTFepH 
/-* SUSSIDS ET PTO TOF »/ 


/* 

peejsut esn O73 Spou PTO eTqeqtTns * 

e eptaocad 03 sqdueqje ‘pt epow e pessed - yoeqTTeyepow y 
+/ 


{ 
/ (zxos) uznqez 
{ 
‘((xos/,u\ (@82NTTeJ=0) XT$xXO Ee rds pepueqzxe-uoU :onaga,,) 6nq)a 
/ ( (SEPOW’ JTOGMETA<-IOS ‘ SOpOWMETA’ SU 
‘,U\XT3x0=sepon<-da ‘xXTSxQ=sepoMMeETA’SU :Onaad.,) 5nq)a 


/ (sug) ueezoguedo(, ueezog 4onr4s)=10s 
adky*su 


STIFLITNEZEG* su 
quog*su 


/» sedkq ¢°T Aquo motte ¥/ ‘aaToxo 3 edAqs<-uqTt 
J@T3798<-UqTT 
iquogesess 
TIAN : dew tqzq<-wqTt é 
((a4¥NLIaWoLsAD 3 edXkys<-wqtTt) 93 (dew3tqzq<-uwqTt) ) 
TION 
‘T 
70 
/ (deep ‘ybty ‘epta ‘epow) yOeqT TesFepour 
{deep 


depatquoysny" su 

sqebpey* su 

uadyoo td’ su 

uedtTteqeq’ su 

SOPOWMMETA’ SU 

yqdeq* su 

fybty qySTeKq’ su 

fOpTM U3PTM* st 

‘90 = ehbpydoyz’su = ebpgaye Tsu 

/* 

KTuo usezoguedo eTAAs pToO E°T XOF wOTReZTTETRFUT su x/ 

} 
(2985) 3T 


{ 


{ (r0z29 ‘epou) beyzozzgepou este 
{ 
{ 
‘() AeTds taxuty{e" 
/ (IDs) ueSeTDSEeXeW 


2((19q04/,U\PT$ = Torr ‘suezrjZouTepzog 7es OF TorquopocepTA,,) Suq) a 


_ ‘(aNod O¥L 
‘SOUL ‘LES SNWULONYTCHOE OVLA 
‘depwxo[oo * 3TOaMETA<-I0s) SHEL TOTAUODOePTA=TIOA 
} 
(ASaR TORTS 
(x98) 3T 


1 ( (20s ‘,,u\xTsx0 38 ros sbeyueezoguedo ‘:onagd.) 5nq)a 


0°U9s9JNS/S8jNpoU 





vices 


: De 


546 ROM Kernel Reference Manual 


[BARRA RE Re Se SRS P rae ene meee Sea eae ae +/ 


{ 
£((s5eq9 (4 weqrbey qonzy4s) ‘wo) TorQUOpDCepTaA) uznqjez 
} 
("7° 4s6e3 SNOTO ‘uoy deWZoToD yonz48) sheLToOTQUODCEPTA TOOCE 


‘(s/,u\sg,,) eessouw (s)7T 
{ 
FTpuc# 
/ (epoozozze’,,u\pT% zorzre epow uMoUyUN,,) ebessour 


3°U9s9IOS/S3/Npow 


:aTnezep 

iyeezq 

/,7UMmouYUN sf GI epou,=s 
*ZQONNMONINN WAASO eseo 

fyeezq 

‘,*;uedo Apeezte uweezos oF[qnd,=s 
*HONOINALONGNd wagso ese 


/yeozq 
/,°@TQeTTeae Jou yesdtyo_meu,=s 
*SdIHOON WagasSoO eseo 


iyeerq 

/,STQeTFeae Jou roRyUOU,=s 
*HOLINONON WAASO eseod 

onaad FopsT# 

syeezq 

‘,'Axoweu dtyqo ySnoue_3oN,=5 
:WHNdIHOON Wagso eseo 

/yeerq 

‘,Xzoureu ySnoue_ jon, =s 
*WAWON wWagso ment 


( epoozorzze ) youtTas 
rueezDs XT80%X0 GI epou uedo 3,uep :onagd.) dnq)a 
iTION=S» 3LAEN 


} 
(epoozozzre ONOIN ‘epow SONOTA) Sswrorzgepow ptoa 


{ 


! ( (xxen<-dt Top ‘xxen<-dt top ‘xutH<-dt Top ‘xutn<-dt Top 


‘,U\pTgskzew prg=xxew pTy=kum pry=xuw :YgENgO.) 5nq)aq 


‘Kxeuw 
ixxeu 


AxeW<-dT TOP 
xxen<-dt Top 
‘KAupu = xutW<-dt pop 
fxutu = xuTW<-dt Top 
/+ GzTop dn Las +/ 


! ( (Autor xutw<-sods ‘,,a\pt% 03 PTs worz asnfpe Aut :ariod.) 5nq)q 


/* 
/* 


‘xuyw<-oxew = Auyu (xutW<-oxew > Auyu) z+ 
‘xxey<-oxeu = Axew (xxew<-oxew < Axew)5T 

Zu - Aupu + qSty = Axew 

! (xUTW<-03%3 ‘XUTW<-sods)NIW = Auyu = xuTW<-sods 
/» dn eaow ‘03x3 Jo doq uweyQ TEMOT FT x/ 

1(L << (ygseq - ySty)) - xUTW<-ogseq = Autu = xutW<-sods 
/* KUWW XIA »/ 


dn 003 x/ 
uMOp 003 x/ 


/ ( (xuqur/xutpW<-sods ’,,u\pT% 03 PT% Wory qsnfpe xuTu :aITod.)Snq)a 


/* 


/x ABT 002 x/ 


/XUTW<-Oxeu xuyw (XUTW<-oOxeuU > XUTU) FT 
7XxeW<-OxEuU xxeu (XxenW<-oxeu < xxewW) JT 
‘T - xuyu + OptmM = xxeur 
I(T << (mQseq - OptA)) - XUTH<-ORseq = xXUTU = XutW<-sods 
/* 3S2IFF XUTW XID * 
* 
SATWTT weoso xew utyqtTM dtTOp eutTzuoo yjnq » 
syerd ueoso 4seq Uo peseq UeeEeTOS EY UAINAOD x/ 
} 

este 


{ 


3F°T 003 x/ 


9°U9919S/Se/NpOwW 





: Source Code 547 


IFF Specification 


/ (z0z2e) urNQez 


/ (qzogzequtzd) qz0gejeTeq 


{ 
/ (dapot) of 3xg°3°TSG 
{ 
/ (dzpot) extaeqesoTtD 


!(dzpot)oreg = z0zze 


iTetoedsoy = TeToeds ot<-dzpot 
uoyzqesoTte Aq pezeeTo /o = smoyqsed_oy<-dzpot 
isToDq3sep = sToD3seq_o}t<-dzpot 
fyors = qybyeqors_of<-dzpot 
‘mois = YQPTMOIs_of<-dzpot 
‘Kors = x02 _oF<-dzpot 
ixois = xozg_o}<-dapot 
isepoy<-da (NOTA) = sepom_of<-dzpot 
idewzojtop<-da = dewzojtop of<-dzpot 
/qro0gqsey<-r0s9 = JIoaqsey_ot<-dzpot 
‘Eaoaadnnd dad = pueuon of<-dzpot 
Sqzoqmeta<-zos97 = da 
} 
(( (0 ‘dzpot ‘9 ‘,, e2taep’ zequtad,,) eoftaequedo=x0728) j) FT 
} 
(((begaaaor 3onz4s) yoozts ‘yzr0gzequTzd) o13xqezee7 (x beyaador 3onz36) 


=dzpot) st 


2 duinpuees9s/sejnpow 


{ 


{ 


‘ueezos © JO TITe ro qzxed qutid [TtM ‘sbetz Tetoeds of pue sToojsep 


} 
((0‘0) qzogeqeezD = 3z0qgzequTId) ZT 


{ 
{ 
‘9T >> (Waptm<-zos / Tdw3) = sTooqsep 
{9T >> TduqQ = Tduq 
= 2 imois = TduQ 
!LO@aSW TwIogds|Stooowsa Twroads = Tepoedsot 
} 

este 
= = { 
‘LOIdSW TwIogds|STooOTInd Twrlogds = ae 


( (QubteH<-290s==yors) 99 (YQPTM<-198==m0A18) 99 (ADIs; ) 99 (xOTS;{)) FT 


/* ®q ptnoys AeyQ AeYyM aqnduwoo om ueyL x/ 
} 
((TeToedsotj) 93 (sToo3sep;)) FT 


/ (z0zz9) uzNAeET (z98j)3T 


*NOISNEWNIddva waddd = r0rTe AUT 
‘Tduy SNOTN 
ida, 3rtogmetA AonIAs 
/qzogzequtzd,  32z0ghsw 3onz45 
‘dzpot, beyaador 7>nz3s 
} 
(Tetoedsot ayoMN ‘sTODAseP ONOT 
‘yozrs qaomn ‘mors quomn ‘Aozs aquomn ‘xozs quomn 
‘ZDsSy weeIDSG 3yONTAS) dumpuseros AUT 


/* 


(y*zequtad/septaep) zorzzgq oF equTad JO sseDons TOZ OQ suUIN_eEY » 


‘useq sary PTNOM 

dumpusez5s eToOYM ezts eyQ OF eATQeTeET dump ezTs TeuocT_OeITT 
e qutad [Tt dumpusezds ‘QyHtey ro YAPTM useexros wors 
quezesystp eze yors ro moxs zo ‘ozezuou exe Aors xo xodxXs JI 


= ‘dump peqoedse yypTM TTnz e z0F 
LOWASW TwIOgds |SiIoOTInd TwIOgds = TetToeds pue 
‘Q=STODAsSep 3e5 TTT dumpueezos ‘AyhHtey pue yApTm ueerzos 
se owes eze yours pue mors pue ‘9 eze ADIs pue xoIs FI “T 
reseD styQ ur 
*seNTeaA ETGeATNs eqnduos o3 LI quem nod seumsse 
()dumpueezos ‘Tetoeds pue sToojsep HLOG TOF pessed st O JI 


‘qyBtey ‘yqpta ‘XK eornos ‘x eoznos ‘zeqjutTod users e pessed 


* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 


dumpusez0s 


* 
~ 


JTpusy 
<y° soqord_qtTe/qtTo> epnTout# 
<y' soj0zd Dexe/qtTo> epnTout# 

SOLOUd ON FOpurt# 


<y°zequtTid/sestaep> epnTout# 
<Y' SUsSeTOS/UOTATAAUT> epNnToUuTH 
<y*sedXk3/oexe> epntTout# 


/* 


* 


(peztnbez jou eszedzzt) qazodqsex dump 03 eutaqnozr - o'dumpuserzos » 


+/ 
3" duinpuse19s/Ssejnpoul 





vices 


De 


548 ROM Kernel Reference Manual 


ZTS ZSaAneA SUTFOPH 


n'STYQ S@8S TOaAou pTNoys nox “QuetTo of wrnjey, 
‘, ‘butsstu yooy yoeq-{TTeo peztnbey,, 
‘,"®TTF AiI ue ION, 

4, °zozze xequds gary 

‘,°qdnzz0> st STTd. 

*zozze yeos weex3s,, 

4, °Z0IZTSE OATIM wee7x3s, 

‘,°Zozze peez weexz3s, 

‘, Azoweu quetoTsznsur,, 

4, °edoDs TeOTXSET ON, 

4° (z0zz@ we Qou) AxXeQUOD Fo pug, 
‘,* (tozze ue Rou) ETTZ FO pug, 

} = []) sbsuz0zz0e, 


/] - zozze- = xpt 
*euo qoezqqns pue ‘qT eqebeu 

‘epoo wagagI xrnoX exe ‘Aexrze sqyR out xeput eyR qeb oL ‘“seuTaqnoz gat 
SNOTIPA WOTF suINAeT E# WWAAAI ETATSsod rox sebesseu rorz9e 7xe]L 


‘,(atun Azeutrd zoz ozez osn) zequmugtun yxqzdtTO :ebesn, = [Jebesn gLzan 


fnz°Le axazdtrTo :ugago\. = []szea aazgn 
/« PUTF OF UOTsTEA:D TOF Hutzy4s wopsreA O°7% «/ 


Z SOUNNIN SUTFOPH 


GNAUALIUM SuUTFOpH 

/* 

A[uo xepeez e& eAeEeTD OF ANO AuUEUMIOD , 

Oe AT peer ueqQ ‘ASIzTF LXLA OATIM OF STduexe sesneD »/ 


sTpus# 

/« Aytteex x/ { ‘(0)umnqez } (pyToa) yzoqexYo AUT 

/x SutTpuey O/TALD eoF33eT eTqestda x/ { /(o)uznjez } (ptoa) miaxD 3UT 
AOILLWI Fopst# 


<y'Bbutzys> epntout# 

<Y°OFpas> epntout# 

<U'aTTPAs> epntout# 

<y' soqord eszedgst/qtiTo> epntout# 
<q‘ soqoizd sop/qtio> epntout# 
<y‘sojoid cexe/qtTTo> epntouTt# 


<y*oszedyzt/setzerzqt{T> epnpTout# 
<Y°Sop/seTzezqT{t> epntout# 

<y° Azoureur/oexe> epntTout# 
<y"sedX3/oexe> epntout# 


/* 
CWAaILIUM SUTFEP# yno quewumos ‘ATuo Hbuypeer Fo eTdurexe we oF ATEAUOD Oo x 


zequmuytun axqzdtto :ebesn 


(aaI eq qsnu eqep pzeoqdtTo TTY) 
EIXLd se 37un preoqdtTS 03 34xeR TIOSW Se3TIM = 79° 3K9gdTTO 


KKK KKK 


atnb 


QET ebtuyw: GIT ‘ATT OT: AIT AMWUMIT 3XQFdTIO OL O° 9xKAFTATTIO‘O"OaIT WONT AUTTA 
p°axasdtto eLf- a- bastzo- tq- OT 
OT'S D S¥S 43TH ou eTTduoD 09 ou oqnodexg - O° 9xQTdTTO x// 


I PYAII/A9YIO 


/* PU® x/ 


{ 
/ (z0zxz9) urN_eZ 
iqsep = qseqd, ‘/enxznos = eoxznosd, 
2 Qpxgzr0r7g 
‘gasitwa = z017z° 
{ 
{ 
(0 < u--) eTTyM { /(>)eqMaangan } op 
‘()eq4aaeon = © 
iqtxgzozzqg 0706 ( 9 > (u =- seqkaasp) ) 3T 
iqyxgzozag 0706 (9 > (T =- seqkgors) ) 35T 
‘T+ u-=u 
} (szTsnuyu =j u) Jt esTe 


{ 

(0 < u--) eTFaM { /(()eqMqqepn)eaaangn =} Op 
‘qyxgzozzg 0906 (9 > (u =- seqkaqsp) ) JT 
/atxgzozzg 0906 (0 > (u =- seqdgorzs) ) 3T 

‘T=tu 
} (0 =< U) ZT 


/* jsseDons y/ 


‘()ea4aqqeon = u 
fqyxgzozzg 0906 (0 > (T =- seqkgozs) ) 3T 
} (0 < seqkgqasp )eTtTyM 


/*« M'dAD & e7ezeueh 09 zeTTduiod eyQ 305 «/ ‘8ZT- = BzTsnutU GuOM 
/» Foot ey ySnozyy 4F Sew om TFQUN Torre oumsse »/ ‘/INUL = TOIT TOOE 
foseqhqqsp = seqkgqsp ‘oseqhgors = seqAgors quom x103stbez 
{> qLAG zeqstbez 
su qiom zeqstbez 
asep, FLAG zeqstboz 
@edInoOs, ALA zeqstbhexz 
} 

(oseqkaasp auom ‘oseazkgors quom ‘3seddy% GLAG ‘eornosdy,s aLAG)MozyDedun ToOE 


/* 
*seqiq seqkgqqsp seonpord 3F TTQun szequTod uot AeuTAQsep pue 
soznos ey3 Bufqepdn ‘moxz ouo syoedun ‘seTqeTIeA UMINIOd OF SUBLNIOd weatS +/ 


‘qseqd, 
feoznogd, 


(>) ea4agngn eutzep# 
()eafaqenn eutzep# 


((2) = ++980p,) 
(+400z2n0sy) 


--------------- moyypegun ----------- »/ 


*zeqnduoo ebtuy-eropoumiop eyy TOF uoTSTEA STUL x 


8zT- 
*seut3 T+(u-) peqeedez eq 03 e3kq Aq pemoTTos : [LZT-*"T-] 
"eqep go seqkq T+u Aq pemoT TOs [uzt"*o] 

:seqhiq Torqu0D 


‘ufeuop ottqnd eyqQ ut sft eremMgAzos sTUL 
“sqzw oOTuorQ0eT” ‘meys eaegjs pue uostxzz0oW Axzec Aq epood uo peseg 


ny zeyoed/dzzT,, OpnTouT# 
eG UGTT/dzZZF,, OpnTouTH 





: Source Code 549 


IFF Specification 


/x 3%eQUOD QxeU reQUe ,/ 


OnUF QUOD (00a wagaaz == TOITS) FT 
S(NWOS asuvaadl ‘FFT) daIeszeg = sag 
(T) OT TUM 
/» SAUNYD SUBD LXLA SY FO TTS puta x/ 


{ 
‘eq 0306 
‘(.°PETTeZ yzUnyodojs,,) sand 
os a } 
((S8HD GI ‘EXLA GI ‘334) AUNGOdoAs = z0rze) ZT 
/x* S¥UNYD SUBD LXLI wo doqs of Quem om eszedyzt ITeL x/ 


{ 

feXkq 0306 

i (u*PeTTeZ peer rox garuedo,,) a 
((awaad daar ‘33T) aatuedo = zozze) ZT 


/= GWHEILTIM «/ FTPs} 


{ (zequmuytzun’,a\ptTs; 3fun pxeoqdt{o peuedoey,,) s3utrzd este 
{ 
tefq 0306 
‘(.°PETTesZ pxreoqdt{To Fo uedoey,) sand 
ee } 
(((zequauyzun) preoqdttTouedo (ONOTA) = weer3s Z3T<-353T) i) FT 


{(weez3s 33%<-33T oe 
(. ©TpueHpzeogdTTD Aonz48)) preoqdtTOesoTD (weer3s J3T<-F3T) ST 
‘Dae 
* 
pzeoqdtTo eyA SsOTO uSeyy ‘STpUeY SEATIM EGR ESOTO ASITA » 
yoeq AF peer uwSeqQ ‘FF EFOTO £,30T MON ¥ 
«/ 


‘(uU\LXLG se pzreoqdtTo 03 3x03 aaa este 
teXq 0306 
!({t - zozze-]sSsuzorze ‘xozze 
wU\S% IPT% Tor ‘peTyezZ SATIM ZAI.) ae. 
(r0z20) FT 


‘(33%) xUnYOdod = rozz0 oer es 
£(3EF%) XUngodog = xorze (x0770j) FT 
{ 
= { 
SLIGM WUIGI = TOITE 


‘(.°e3ep sun BSuygtim z027g,,) a 


(weTqxe3 =; (ueTQxeQ ‘3xeqku ‘33Z7) se3Aqyunyoe TIM) JT 


/(qx0QAu) ueTz@Q46 = uEeTQZx0eQ 
/* (3%03 ©43) BQeEp TenQoe eyQ MON x/ 
_ i } 
CC(NMONOINA AZISadI ‘SUH aI ‘oO ‘FFF) AUNYOYsng=202720e) j) FF 
/s 
“SYUNYO STOW SEATIM PTNOD NOX » 
"MUNYSD SUHD EMO E{TIM Jenl TT,OM * 
eqep yungo eyQ Aq pemoTTOS GI AUNYO SYHO YQ MON »/ 
he. _ a? } 
CCONMONOIND AZISaaI ‘WaOd GI ‘IXLA GI ‘FFF) AUNGOYsng=r0770) ;) FT 
Js 
(EXLa) GI WHOd O43 OFTIM ‘Q8ITI « 


* 
IXLI WAOd UT AUNYS Sun se pzeocqdtTTo syQ oF 4xeQ ANO EQ{TIM » 
a/ 


{ 
fekq 0305 
i(.°PETTeF O9TIM ToZ garuedo,,) at 
((3LIUM daaI ‘3Z4) aaIuedo = rzozz9©) ZF 
/s 
“UOFQOesueITA AGT SYR ATeAS x 
a/ 


CVaUALIUM FOPITH 
(334) d¥TOsegzI3tUr 


{(zequmuytzun’,u\prTs 3tun pzeoqdtTo peuedo,,) squtzd este 
20ekq Se 
/(,°pettez uedo pzeoqdt{o,,) sand 
(((zequmuqtun) pzeoqdttTouedo (SNoIn) = Gesdad ave asia xt 
"O/I pzeoqd}tTo z0z eTtd gar dn eee 
* 


{ 
tekq 0306 
S(u°PETFEZ ()gGgIDOTIW.) sand 
} 
((Q) gaISOTTy = har ras 
_ * 
*@INGONTAS OTTA FAI SREOCTIV » 
«/ 


{ 
tekq 0706 
£(,°Azxezqtt Bbutszed zz uodo 3,ueD,,) sand 
} 
(((to ‘,Azexqyt*eszedsz},,) Arezqypiuedo = esegeszeadaar) i) FF 


{(({t]s62e) toqge = xzequmugtun 


{ 

! (NSWM NUOLMI) 3txe 

{(ebesn’,,u\sg,,) squtzd 

} 
((,é.==[0] (T->62e] abze) | | ( (SOUVNIN>Obze) 93 (OHze) )) FT 
/x ebesn qutizd ‘,¢g, zo shze ybnoue jou Zt x/ 


‘[zsanqa]snqpeex aLxan 
SUETIXSQ QUT 
fueTz ‘o=zZequmuytun ‘o=zr0rzTe Huot 
JUD_y SPONRxXEQUOD QONIQsS 
“TION = 53k STPUeHAIT youzys ) 


(abzeyy zeyo ‘ofbze Aut) uTeuw ptoa 
/,u\‘etTduexe 3x43dtTo Aq preoqdyTo 03 ueqqTIM LXLE STYL.=([]3xeq4u FLAEN 
fesegeszeggdiIyx ArexqTT AonzAs 


SUHO_dI euTtzep# 


(.8./.8,/.H.'.9,)01_SaWn 
LXLi GI eutzep# 


(.0.'.X.'.,'.d,)dI DW 


I PQjalja/ABYyJO 





vices 


De 


550 ROM Kernel Reference Manual. 


JyOELTEGeuo =- Wunoo<-ofo 

‘sax = ebueyoAue 
(yOTTASGeUQ =< yuNnoD<-ofkd) ZT 
teqez<-oXfd =+ qunoo<-ofo 


= senutquoS 
( (SIWION ONY == 93e2<-DAd) 
I| (0 == (aArLOW onassbetz<-of5) ) 
tl (a6 tq<-245 == mot<-0Ad) ) FF 
{[¥] seToAoy = ofd 
} (++ SSOXONXWHD>T /O=T) TOF 
‘on = ebueyodue 
} (ButtoX5) zt 


7FTpuc# 
usepuscf# 
ye‘te [T° eaow 
(ds)-‘_p-zp/Le-ze 9 [ weaou 
=! use# 
DALZY SI FOPrT#H 


f‘ebueqoAue Tood THOOT 
idueq daoM TYOOT 
‘oko, efuey WOOT 
If’ aut 

} (avetTan4n 


iszoToou ZaoHS uzeqxe 

fqzoday 320gmMeTA QONnzQAs uUrTERXe 
‘[]stook> qaiom uzejxe 

‘[(] Sut pox ood uzr983xe 
{[]setoko ebuey uzeqjxe 


09/%AOTLTEAOuO Degzegeuo sutTzepH 
PSE9T AOTLTeGeuo eutzepH 
/*= se3e2 euexz ButToOAD x/ 


/s ETOKD 3,U0p ‘FLWION == 93e7 St ¥/ YE ALWHON_ONU SuTsJepH 
@ FSUIATA_ONA eutzep# 

T ATLOV ONY SUTFEpH 

/» sentea sbetz obuey ,/ 


‘ebuey { 
/» ebuez yo spunog »/ ‘ySty ‘MoT aLxGA 
‘sbetz LYOHS 
/eqezx THOS 
iquno> LYOHS 
} qonzqs zepedAy 


DFIeAs TWOOT euTzopH 
SOUL SAX SutzopH 
aST¥d ON eUuTsepH 

b SOAONKXYN SUTFEPH 


<q" xeTTdwoo/sJFT> epntout# 
<q meta/sotydez5> epntout# 
<q°sqdnzzequt/oexe> epntout# 
<q" sedk3/oexe> epnTout# 


/* 

zor uo A- a- sheTz epntout ‘sws yar peTtduom ZI * 

Buy{TokD xoToo ueatap 3dnzzequyt z0z eTduexe ue se quewberz styQ osn * 
x 

epoo adnazequt ButToAD xzoToo AutTegd s,BATTS ueq --- o°qadAD 


»/ 


9°QN0A0/104}0 


‘(a0 NUALTa) 31xe 


(esegqoszedddI) JT 
{ 
*(F3T) garTeerg 
2 /* 
“FTOSFF SANQONAAS STTA AAI SYR Ser » 
a/ 


/ (esegeszegaar) ArerqTTESOCTO 


{(wreez3g 33 7<-33F 
(x OTpueHpreco(dtTD yonz3s)) preoqdtTTOes0eTO = =___ 
(weez3s J3T<-335t) FT 
/* 
weeiqs pzecqdt{[o ey esS0TD » 


»/ 


(334) dalesoTo 
/* 
*seanqQonzAs peqetoosse [Te x 
eerq ‘“weezAs 2eYQ YITM WOTQ_OesueIAQ AAI SYQ oQeuTwureL » 
+/ 
} (337) FT 
:0kq 


{ 
Z(({t - zozze-]sBsuxoxze ‘xozrze 
‘,U\S% IPTS zorze ‘peTTexy peezr JAIu) zqutad 
= } 
((80% WIAIAI =j TOIT) 99 (TOTTS) ) FT 


{ 
{ 
(0 > uweTZ) FF 
{ 
/ (ueTz‘gynqpeexz ‘ () gndqno) e3tIM 
} 
(o < ((zsanqa ‘snqpeez ‘z3z7) seqkqyunyopeey = uweTr))eTTYyM 
i(,u\isuptegquoo yunyo SEG IFS 
((SHHO GI == aI wo<-u>) 33 (~EXid GI == ed&y uo<-uo) 99 (uo) ) FF 


/ueTI = zr0orz79e 


{(F3FT) yuNYOQUeZAND = ud 

/* 

eqQep UNYS SUHD SY Peod + 

yunyo doqs © TY eA,eM TOTTS ou FI x 
syUNYO SUH LXLI 3e doqs 03 peyse ATuo om ¥/ 


fyeexzq (rorrTe) FT esTe 


°YXPYAL]I/ABYIO 





: Source Code 551 


IFF Specification 


Su€°LE weosuqTT :ugA$o\. = []sz0ea aLAGA 
/x PUFF OF woFsreA:d TOF Huyzqs wopszen 0O°Z */ 


Z SOUYNIN euTzEpH 

‘(4 STPUBHGII 3ONTQS) OFUINGTIZUTId PToa 

(1%.'.0.',0,' 8.) I_SWW KGO@_dI eutzop# 

(49./ UW.‘ WN.‘ 1D.) 01M SWWO_AI eutsep# 

(ids! MW! Ws’ 1D.) CT_ DIA aYWO_AI eutzep# 
‘ 


(.0./.H,’ Wa.’ .&,) aI_SIW GHWa_dI eutzeop# 
(1W.‘.8.',T,',I,)aI DW WETI dI eutszep# 


fyunyobuea { 
sepoymMeTA SNOTN 
} qonzqs zepedx 
/s @INQONAAS sepouMETA (ONWD) eHyury exopoumtoD ./ 


‘xepeepdenqta { 
‘qubteqebed ‘yqptmebed qaom 
iqvedswx ‘qoedewx aLxan 
{zoTopjuezedsuezy qaoma 
‘tped gizqo 
fuofssexduop FLAG 
‘buyysey = FLAGA 
/x seuetd Jo # x/ fseuetdu aLxAGOQ 
/x deagtq styz zoz uozatsod A ‘x x/ ik 'x maom 
/*s stTextd ut aqbtey ‘qaPTM x/ ‘q ‘m qaoma 
} qonz3s zepedx3 
/» exznqonz36 (qHWd) Zepeey deuyta +/ 
* 
sETTF SpNTOUF ut pepfaoazd eq osTe xew pue i 
Waod & r0ZF peds ey UF peUTyep ere serangQonazyAs yous * 
syungo ,OWWO, Pue ,GHWa, WETI Weod & FO eTNQONIAs eCUL x/ 


yTpueg 

/x Atyeez x/ { ‘(0)urngez } (pyoa) yzoqexYyS AUT 

/»s Suttpueyg O/TULD eoFaazeT etqestd «/ { ‘/(0)urnqez } (ptoA)miGxD WUT 
FOILLWI Fopst# 


<q" butzqs> epnTout# 

<Y°OfFpAs> epnTout}# 

<U°QtTP3s> SpnTout# 

<y*soqozd eszedgzzt/qtiTo> epntout# 
<y’soqozd sop/qtTo> epntout# 
<y*soqozd pexe/qt[o> epnTout# 


<Y*oszedszT/seTrerqtT{T> epntout# 
<Y‘sop/seyTrerqyTT> epnpout# 

<y° Azouweu/oexe> epntout# 

<q" sedk3/oexe> epntout# 


/* 
qemyos oe y pue uosnhzeqg yzenqgs Aq Aq 0-azts uo peseg x 


<@T}Z> uwedsuqTT 10 


Hbuyuueos ettsy sod roa 
D- ueosuqTy :ebesp 


‘ 
Huyuuess pzeoqdtTo z0g / 


8 ,WEII TT® T0F STF AAI ue ySnozyQ sueos 
S,WATII JO ‘930 ‘epou ‘qoedse ‘ezts eyq squtTid iD UBDSUqTT 


eeEKe KR KK 


atnb 


QtT ebyuy: aIT ‘ATT “OT: AIT AUWUGIT uedsuqTT OL O° uUeDsSUqTT ‘O° SD: qIT NOUd AUTTA 
D-ueosuqTt e€Lf- a- bastzo- tq- 1 
OT'S OD SYS UITM ou oTTduod 03 oul eANoexg| - SO ueoSUqTT «// 


D"UBDSWIG|!/JBYYO 


/ax/ 
{ ‘(azegqutys‘s)zeazesquruey } () xweTaAdo3s 


{ 
+ (4208 UT9 ‘G) TeATeSQUIPPY 
‘oureudur = eureN _UT“SPON ST“ ATS QUT 
_‘0 = F2d_UT" Spon st -azesqut 
‘LGNWaaINI IN = edXy_ulT"“epon_st*azesaut 
TION = perd_UT "Spon st“ azesqut 
'TIAN = Dong UT“ Spon st“ azesqut 
‘yueTaAAWs (OUNEPTOA) = EPpOD st" AzTESQUT 
i FTpue# 
TION eyed st Ares uy 
es esTo¢ 
Jax ve zeystbez Fo squequoo suznqez y/ /()OsLZWLID eqeq st Ares uy 
OFLZW SI FOP t# 
} ()xueTaAIzeIs 


!() (pungptoaAs) pyToa zoped%R 


fazegquy ydnzzequr 3Oonz3s TYOOT 
/» xeTpuey ydnzzejutT Fo eueNn x/ ‘,aa4n, = []eueudu zeyo TWOOT 


/* 
zeTpuey qadnzzequt BbutToAD eaouwez/TTeAsSUT O02 EPPOD 


x/ 


{ 
/* 8FYQ Op Of EAeY soUTQnOZ AdnazzeqUT x/ /(o)UurNQez 


sTpue# 
wsepus#¢ 
LP-zp/Le-ze‘+(ds) T"weaou 
use# 
/» Azessooeu st sty «/_ ? 


OALZW SI FOPI TH 


{ 
{(szoToou ‘stTooks ‘3z0da) paoupeolt (ebueqoAue) ZF 
{ 
; { 
i!dueq = [Mo[<-o0fd] spooks 
2(t-E] stos%s = [f] stooko 
imot<-oko < € /ybty<-oAo=£) zoz 
£(yBty<-245] stopA> = dureq 
} este 
{ 
iduweq = [(Mo[<-o%5] stooko 
/(t+€] stoods = [f€) sTooXo 
tybty<-of0 > € /mot<-ofo=f) z0z 
{ [moT<-040] stooko = dueq 
} (asudama onassbeTz<-o45) 3T 


2°QA0K9/10U}0 





vices 


: De 


552 ROM Kernel Reference Manual 


zeyjo Aue st ezeyqA FT doot eyQ oeaeeT 
*/ 
(xozze) J} esTe 
{ 
fenutquoD 
1 (.U\U\NEIL WOT SUA Oe I 
(00a wiaddI == roxze) zz 
—, * 
“squese (D0q ) QxeQUCD-FO-puS ,PISOSTP, SAM » 
‘qxeQu0> e& zeqUe om ueYyM UT peqsezequT ATUo e2,0M eDUTS » 
a +/ 
(NWOS EsSuvdsdI ‘F3F)Aaleszeg = r0rze 
} 
(Tt) OTTGA 
/* 
8 ,WATI WAOT PUTT OF » 
sqeux0sy xeTduiod erou OUT SATOP SN AOET TTT@ (T)STTUM SUL x 
*ueos eq3 Od »x/ 


‘(WaOd_GI ‘WAII AI‘334) 3¢xXaUOdoAs 
/*« WHII Waod & HuyaeetT weym (D0z wMigAgI) MOUY sn 3ET PUY +/ 


{(xa0@ GI ’WAII GI ‘334) xUNYOdoAS 
/* Kdom ©FQ 3e dojs x/ 


‘(aqWWO_GI ‘W@TII_aI ‘334) xunyodozra 
7( ( aI ‘33 F) xunyodorg 
‘(QHWa GI ‘WATI GI ‘3F+) xanYodoza 
/* DAY PUS CHWA FOCSETTOD 02 QUEM OM x/ 


{ 

fekq 0306 

i(.*pettez aaruedo,,) s3utId 

a } 
((awmad aaaI ‘33T) aaruedo = xorze) FF 
/* 
“UOT QOesuUeTA TIT OY WTSIS + 
+/ 


{ 
# (337) ears 
feXq 0306 
‘(w"peTTez wedo reas 
(((@IZaq@IO aGOW ‘[T]a5rze) uedo = weer3g 334<-33T) es 
* 
e 
a/ 
} 


{ 
+ (337) Seor seer 
40Xq 0306 
*pettes uedo preoqdtTo,,) s3utad 


se } 
(((aI'%D AUWNIYd) pxreoqdtTouedo (DNOTO) _ 
= weerqys J3T<-33T) ne 
is * 
‘O/I pzeogdtTD zoF CTT AaI dn eg » 


"0/I soaeStuy z0z eTta aar dn es 


2 UBISUIG]!/J0U}O 


(oFqD) ry 

* 

*eseo yore zoz suoTQeutyoeu ejetrdordde , 

eqQ suzoszzed Queuejejs ,Jt, SETTEZT sTuUL “eDtAep*pzecddyTO » 
eyq pue ‘setts sodebtuy qy20q z0z peptacad sy} yz0ddns TeurejuI » 
+/ 


{ 
teXq 0306 
i(u°POTTEF () daIDOOTTWn) eae 
((Q) ddIPOTTW = F3F)i) FF 
= /* 
"@ANQONAAS STFA AAI SFESOOTTY x 
*/ 


{ 
tekq o706 
i(,°Azezqyt Burszed zz7 uedo 9,ueD,) squtId 
} 
1, Azerqtt eszedzzy,) Azezqyquedo = esegeszeqgiI) i) FT 


(,9, == [T]l[t]s6ze 933 ,-, == [o] [t]s6ze) = wi 

* 

*pzeoqdtto e423 03 0/1 Sutop eze om FF EOS OF YOoUD » 
+/ 


& { 

2 (30 NWOLAA) 3Fxe 

/ (ebesn’,,a\sz,,) szutazd 

} 
((,6,==[0] (1-05ze] abze) | | ( (spuWNIN>obze) 93 (obze) )) FT 
/* e6esn qutad ‘,g, xo sbxze ybnoue jou ZT x/ 


iofqo qxous 

{zozze Huot 
TION = FFTx STpueHadI yoNTAS } 
(abzeyy rey ‘ohze Quy) utew ptoa 


feseqesreagdIx AzexqvT 3onz3s 


un’ STYQ S885 TEaASU PTHoys nox “AUeTTO Of urNQeY, 
‘, Bupsstu yooy yoeq-TTeo pertnbey,, 

‘w"OTTS ddI Ue ION, 

‘,,’xozze xequds gar. 

qdnazop sft STTdn 
‘, °Tozze yeos weer3s, 

4, °ZOITO OATAM weexqs, 

‘,"Zozze peex weexz3s,, 

‘, ‘Kzowew queyvoTssneul,, 

4, °edoos TeROTXST ON, 

‘,,° (r0ozZe We Qou) A4xeQUOCD Fo pug, 
‘,* (zozze we Jou) ETT FO Puga 

} = []s6sur0zz0, 





iT - xozzxe- = Xpt 
*euo.qoerqqns pue ‘41 ejebeu 

‘epom wugadI znoX exyeq ‘Aerze styQ ojuy xeput eq3 qe6 og “seutqnoz gar 
SNOTIEA WOTF suIN_eT é# WiAAGI STATssod roz sehesseu torre xe] 


2, (pxeoqdtT> zoyz o- xO) eueueTTsqdiI uweosuq{Tt :eBesn, = [Jebesn azzqn 


D"UBDSUIG]!/48U}0 





: Source Code 553 


IFF Specification 


{ 

/ (sepo_metA<-bured ‘,,u\u\xT80%$_= AIepoN :ONWO.,) F3UTId 
feqeq de<-ds(, yunyoburep) = bureo 

/* OMWO UF BQep 03 rAd st eed de<-de ‘onWO st Agzedozd 31 * 


este 
_ ‘/G.:a\punez SNWO ON.) FQaTad 
(((onNWO GI ‘WHII ar ‘33t)dozaputa = ds) va 
* 
ONWO Azedozd pez0js eq3 03 z9eqUTOd e 34e5D » 
«/ 


{ 
(e / ezts de<-ds 
‘,U\szeqsTbez ply Toy senTea qoU suTeQUOD :aWWO.,) F3UTId 
/= MOND UT e{ep 09 3AAd st eQeq ds<-ds ‘awWo st Aqredoad ZI x/ 
} 


este 

— ‘{(.t\punoz ayo oN.) s3uTad 
(((auno GI ‘waII aI ‘33t)dozaputa = ds) a 
* 
awip Azedozd pezojs eyQ 07 ZequTod e 3e5 » 
«/ 


{ 
qoedsy X/x ») Fqutzad 
zojToosuerL uw) Fqutad 

uot ssezduop uw) Faatad 
Sut xsew wo) zqutzd 
seuetdu ow) FQazad 
a3yubtenqebea uw) zaatad 
qaptmebea u) Fquzad 
qySteq ») Fquzad 


2 (qoedswx<-pyuiq ’ qoedsyx<-puyuq ’,,U\PT$/PTS 
{ (zoTopquezedsuerzi<-paugq ‘,,u\PTs 

/ (aofssezduop<-pyurq ’ ,,a\PTs 

/ (bupysen<-pyuq ’,,a\pTs 

/ (seuetTdu<-—pyug ’,,u\pTs 

! (qubyepebeg<-pyurgq ‘,,u\PpTs 

‘ (qaptmebea<-paqudq‘,,u\prts 

! (a<-pyuq ‘,,a\PTs 


D"UBDSWIG]!/JB4JO 


/(m<-pyiq’ ,U\pTs = UIPTM :CHWE,) s3uTId 

feqeq ds<-ds(, zepeeqdeyajta) = pywq 

/* GHWG UT eep 03 14d st eqeq ds<-ds ‘quwa st Aqzedoxd ZI x/ 
} 


_ ‘(ut\puroz GHWa ON.) s3uTId 
(((qHWa GI ‘WaII GI ‘33t)dozaputga = ds) pe 
* 
auwa Azedozd pazojs eyQ 03 zequTod e Ae5 » 
»/ 


/fureay. yunypbures 
‘puUdy, zepeondenata 
ids, Kyjzedozgperz0ys yAonz48 


esto 


} 

‘334% STPUBHAAI QONTAS 
(FFT) OFUINATIAUTIa 
PTOA 


i(30 NunLma) 3txe 


{ (eseqeszeagar) ArexrqyiesotD (esegoszegaar) JT 
{ 
(J5T) AIIeerd 
= /* 
“FTOESAT SANQoONIAS STTA JAI OY SOTA » 
«/ 


/(weez3s J3T<-33T) ES0TO 
= ; esto 
#(weez4s JFT<-FFT 
eTpue_pzeoddtTD yonz34s)) preoqdtToesoTO 
(ofq2) ZT 
(ureezqs FFT<-33t) FT 
/* 
“FTOSAT weexr{As Sy ESOCTO + 
*/ 


(337) g@aI@s0TS 
/* 
*“SOINQONIAS PEQeTFOOSsSe TTS » 
"weerjs 243 YAM uoTQoesuery GII Suz eqeupwroeL x 
a/ 
} (334) 3T 


J(({t - zozze-)shswr0rze ‘xz0zrz1e 

‘,U\S% :PT% ZOTTS ‘peyroge ueds eTTE,)F3UTAd 

esto 
£(,u\teqeTduos ueos eTTa,) F3utId 

(40% WaaadI == rTor7e) 2 

* 

‘otqsoubetp e qutid em ‘estMreyAO “sueTqord qnoyAyM STTF Sud * 

JO pue oyy pezequnooue zeszed oyQ wey ‘40 WAAIAI sem TOTS JI x 


«/ 


{ 
+ (FF) OFUINATIAUTAa 

/* 

(xqo@) xUnYD dojsg zno je ere OM y 

ueew prnoys zorzze Orez ‘NYOS ASUWddAII PTP OM CDUTS » 
ozez sem zorze ‘ezey 305 eM JI x 


«/ 


D"UBDSWIG]!/J94IO 





vices 


: De 


554 ROM Kernel Reference Manual. 


{ 
fekq 0306 
‘(,*petyez uedo eTTa,) sand 
= = } 
(((aIIaqIo zaow ‘[t]abze) uedo = weez3s ger esi AY 
aS * 
"O/I soaebyuy rox STtA JdI dn 30g » 
«/ 
} 


{ 
i(z34%) AeTOsesaratar 
{ 
tefq 0306 
‘(,*pettez uedo pzeoqdtto..) sand 
= } 
(((aII> XUWAIUd) pzeoqdytTouedo (SNOTA) 


= weez3s J3t<-33T)i) FT 
2 Js 
"O/I preoqdtto z0z ETTa aa dn 20S 


(Ofq>) ZT 

/* 

‘ese yore oz suoTqeuTyoeu ejetirdordde 

eq suzogzred queuejeqs ,JT, STTEZTQ StyL “sotaep pzeogdtTo » 
ey3 pue ‘setts soaebtuy q30q z0z pepyaord st jz0ddns Teuzejur » 
«/ 


{ 
fekq 0306 
P(u'POTFEZ () dAIDOTTWn) — 
(CQ) ddIDOTTW = F3T)i) FF 
= /* 
"OANQONIAAS STFA JAI SAVSOOTTY x 
+/ 


{ 
feXq 0306 
/(,°Azezqtt 5uazezed zz~ uedo 3,ueD,,) sand 
} 
(((10 ‘,AzerqyT*eszedzzt,) AzexqyTuedo = esegeszegdiI) i) FT 


$(.2, == (t]{[t]a6ze 33 ,-, == [o] [T]abze) = otgo 

/* 

*pzeoqdt{o ey 03 0/1 Suyop eze om FF SEs OF YOoUD x 
x/ 


{ 

fekq 03705 

/ (ebesn’,,a\se,,) Faatad 

} 
((,é,==[0] [T-o62e] abze) | | ( (SouwNIN>>b2e) 33 (Dbze) )) TF 
/+ e6esn quyad ’,¢, x0 shze ybnoue you st x/ 


ZoTqo qroys 

{zozze Suot 

'TION = JIT eTpuegddI WONT3AS 
} 
(o6zeyy TeYD ‘ohze Aut) uteuw pfoa 


fesegoszegaarIy AzerqypI Aonz345 


I YIS/194}O 


un’ SFYQZ SSS TOASU PTNoYs Nox “AUeETTO OF UINQe", 
‘, Suysstu yooy yoeq-TTeS peztnbexy, 
‘,°SOTTF JaI we ION, 

*zozze xequds gary 

‘,*'adnzzoD ST ETTan 

‘,"ZOorIe yous weexgs,, 

‘,"XOITS SOATIM weex3Qs,, 

‘,°ZOxrze peex weexz3s, 

‘, ‘Azouwew Qquepfotssnsur,, 

4, °edoDps [TBDTXET ON, 

‘»° (z0zIZ® ue jou) BxeQUOD FO pug, 
‘y* (tozz@ ue Jou) ETTF JO puga 

} = [] sSsuzozz08, 


‘ft - xozze- = xpt 
*euo 30erAQqQNsS pue ‘QT e7ebeu 
‘epod wagaaI rnok eyeq ‘Aezze syyj ojuyT xeput eyR yeh OL ‘“seutTQnoZT ZAI 
SNOTABA WOTF SsUINQSET Z# WUIAAI ETqtTssod rzoz sobessou rorIe 4xeL 


2(% STPUeHAAI ourAs) yunygodoLAutszgd pToa 
/* woyyounzs zno rox ojoArd ,/ 


!, (pxeoqdtT> zoz D- zo) eureueTTFgdI asts :ebesn, = [Jebesn gzixGn 


‘uT°LE aFFts SURASO\. = []szea aLAGN 
/* PUTF OF woTsxrea:d Tox Huyzqs uotszep O°Z x/ 


Z SOUWVNIN SUTFEPH 


FTpuc# 

/« AyTeex »/ { ‘/(o)urnqez } (ptoa) 3roqeyYo ut 

/« Suyrpuey O/TALD eotaqeT etqesta «/ { ‘(0)urnjez } (ptOA)MIGXD AUT 
AOILLWI FOP tH 


<q" Suyzqs> epntout# 

<Y'OTpAs> epnTout# 

<U'QFTIP3s> epnTout# 

<y'sojozrd eszedzzt/qtto> epntTout# 
<q° soqozd’ sop/qtto> epnTout# 
<y*soj0zd Dexe/qtTo> epntTout# 


<y oszedyzt/setzerqy[> epnTout# 
<Y'sop/seTrerqTT> epntTout# 

<y Azoueu/oexe> epnTout# 
<y*sedk3/oexe> epntout# 


/* 
qemyos oe7y pue uosnbzeq qzengs Aq Aq 9°33 ts TeuthyIo uo peseg 


“ITD © wory unz eq ysnu wexrbord sty, 

*p- zoz dtto Azewyzad s,pazeoqdtT> eyq st zo ‘Queumbze 

<©TTJ> ZOF ETTF Sod & st weeryg “Aue JZ} ‘OTTF AAI CYR FO syuequod 
eya FO HutAstT SexTT-AoeyoTGI we squtTzd pue weez3s petzyoeds eyQ speey 


<®8TTS> AFFS TO 


Huyuueos STTF sod roa 
D- agts :ebesn 


butuueos pzeoqdt{To z0q / 
*gJynAs Tooo 3eYQ TTe pue xequis 
SOTFTIOA “AT UT S,QeYM NOA sTTeR pue eTTS gar Aue soyez :D°4sTs 


REE RK KKK KKK KKK 


nb 


QTT ebtuy:alT’ATT OT: GIT AUWUGIT AFTS OL O'AFTS‘O°D: GIT WONT AUTTA 
p-azts eLf- a- bastyzo- TqQ- oT 
OT’S D0 SWS YAM ou eTTduoD OQ Sw eQNoeEeXx” - O°AsTts afi 


OYIS/A94IO 





: Source Code 555 


IFF Specification 


i((gnqpt ‘edAy uo<-doq) z3s03qI) sand 

/* 

*eut—TMeu e yqtam ‘edXkQq s,yunyS quezind eq AuUTId » 
x/ 


i(eztgs uo<-doq ‘(gnqpt ‘qr uo<-do3) z3s03qI ‘, PT S%.) FQuTId 
/* 
‘ezTts pue dI s,yuNYyo quezind syy yNo AUTId » 


«/ 


Sa la) ZF3uzad 
( ¢-- ¥ ‘yqded J3T<-3FT = 1) a 
* 
“pequeput no pequtad » 
eq 03 syUNYS peqseu esNed TITM STUL “eZ OS pessedord syuNyo y 
sO yqdep Bbutqseu quezino eyQ o3 queTeatnbe sjop so setxes © AuTId » 


«/ 


Jurnqez 
(((Z3T) AUnyOQuezanD = do3)i) ZT 
/* 
“qxequop quezino eyQ BbutqtzDsep epou yAxequoD eyQ 0A requTOd e AeD » 
*/ 


[gs] snqpt xeyo 
fs: qzoys 
fdo js SPONZXEQUOD 3oONnzAs 


} 


‘337 STPUBHAII WONzTAS 
(334) yunyodo,aqutza 


‘(90 NunLwa) 34xe 


(esegqeszeddal) FT 
{ 
(FFT) galeezg 
= /* 
“FTOSIF SOANQONTAS STFA AAI CYR SETI « 
»/ 


/ (esegeszegaar) ATerqTTEsoTO 


/(weez3s J3T<-35T) ESOTO 
= esto 
/(weezqs J3IT<-33FF 
(x @TpueHpzeogdtTD 3OnzT3s)) preoqdtTOescTD 
(oTqQ2) ZT 
(weer3s J3FT<-335T) FT 
/* 
“JTOSAT weexrqs EY S50OTD » 
a/ 


OYIS/A9YJO 


PToA 


i(F3T) AsIIPsoto 
/* 
“s@INQoONTAsS peVeToosse [Te » 
SeTq ‘“weerqs S49 YQTM UOoTQOesuUeTA ZAI SOYA oQeUTUTEZ » 
*/ 
} (334) 3F 


£(({t - zozze-]shsuz0oize ‘rorz10e 

‘,U\S% IPT% Tozze ‘peqzoge ueos eTTga,) zF3utad 
esto 

i(,7@qeTduo> ueos_eTTa.,) sand 
(40a WaAGII == TOITE) FT 
/x 
‘otqsoubetp e qutid em ‘estmzey3Q “sueTqord qnoyqtM eTTF Sys » 
JO pue syQ pezejunoDSue zeszed oyy usyy ‘JOU MIAIII Sem TOIT FI 
«/ 


{ 

‘(334) yunyodoLqutza 

/* 

“sijtezyye FO ajeqs QuezrNS eYyy 4no AuUTId » 
*ozeZ sem rOTXIe ‘azey 3eEH OM FI « 


«/ 


iyeezq 
/* 
‘zozze zeyjo Aue sft ezeyy Ft dooy eyq eared , 
»/ 
(z0zz9) JT esTe 
_ fenutquoa 
(90a WiaddI == Tozze) FT 
= /* 
*squeaes (DOU ) 3xeQUOD-Jo-puS ,PIEOSTp, OM » 
‘AxeqQuoDd e& zeqUS OM USEeYyM UT peqsezequT ATuO e27,eM BDUTS » 


*/ 


!(43LSMWa ASUWdddI ‘FF) AATSesred = TOTS 

/* 
*zozze Bbutszed wv <este Bburyqkue> 
“eITF-JO-puse pezequnooug 404_WagaaI 
*qxequoOD eB eARPeT 073 AnOQY dog Wasa 
“QxeqQuUOD meu peze jug ° 
iuoseey lepod urn yjeY 


rsuoseez BbutTMoTTos ey soz shutyQ butmoTTos 

Sy UINQST TITM daLSMWa UATM ()gaTeszeq “STTF JaI 

ue JO erznjonzyAs eyQ QuTazd of YystTm om Z4 Azesseoeu st 
yotya ‘ssecord butszed ey zo butzoqtuow uotstoeid eary 
03 sn sqtuzed qaLSMWd ASuUvdddI “3tq HButqsezequt euyL 


Ke KR KKK KR KK KK 


* 
ms 


(tT) eTTIM 


{ 

feXq 0306 

‘(7 pettez aaruedo,) sqnd 

a } 
((aqwaa aaaI ‘F34) aaIuedo = TorTe) FT 
/* 
‘uoFQoesuezy JAI SYR ATeIS « 
»/ 


{ 
S(337) SodseaaI tur 


IYIS/ASYIO 





vices 


De 


556 ROM Kernel Reference Manual 


appendix B 
EXAMPLE DEVICE 


This appendix contains source code for a sample device. The example code is an excellent starting 
point for those who want to create a custom device and add it to the Amiga’s system software. 


The example is a complete four-unit, static-sized RAM disk that works under the old (standard) filing 
system, the new Fast Filing System (FFS), and has optional code to bind it to an AUTOCONFIG™ 
device. 


The examples have been assembled under the Metacomco assembler V11.0 and under the CAPE 
assembler V2.0. 


Example Device 557 


nda S@_S3AIua 
00a s €gATaa 


# pueumos TebeTTT yexTF -- reyxTeEU eoe{d GNZ ASGAN GWOAgG 
(40-ON ) 3dnazzequt ebueyo yetp eacuey / LNIZONYHONEY_GNO 
(40-ON) 3dnzzequy ebueqo xSTP ppy ‘ LINIZONWHOGGY_GWO 
syoezq Jo zequmu ep / SYOWELWONLAD_GWO 
edk3 eatzp 3°5 / FdALAATUCLAS_AWO 
peqzoddns 30Nn ALTamMMwd_dwo 


pejzoddns 30n awamwe_ 
(astva sXeate) ~peqoejo0id eqTIM ysTp eqQ ST SOALWLSLOdd_dWoD 
(gouz sXemze) geatip eyy Ut ASTP e ere st GLINVLSZONWHO_dND 
(o sXemte) sebueyo ystp FO zequmu WONGSNYHO_dWO 
(40-ON) sebueyo ystTp ueqa AzZTQ0U @AOWaa_CWO 
MSIGHWa TOF ALTIM 02 peqenbe - ysTp yewros Twod_dwo 
(d0-ON) Yeos QTOTTdxe 4aas_dno aqaoAad 
(40-ON) ZOQ0OW s,xASTP EYQ TOTQUOD AOLOW CWO 
LINIAIG 


iii spueumod ,pepueqxze, T0F ST ‘WOOLXa ‘GL dadLia 


ssezppe jesex Adnazzequt s,preoq AW 
pzeoq uo Aeszzo x9eqjsthex Toxrqu0oD 34dnzz206834UIL 
preoq uo yeszzo zeqsthHez Tor3u0D ydnzzeqUL 
ZTIOLNI FO AT ,eTQeug ydnazzequI,, 
TTMOLNI FO 37q ,,3dnzzequy eyQ Suytind we 1, 


AUOLOAS suAdSaOLOIs Noa WOWALUAdSALAG 
ayun zed Wva youu styQ esp / 
UAIdSAUOLOTS x SHOWVALAONAANON*+YOLOIS nda aZISNWa 


w4Der3,, ed szoj00g #/ OT nda wgaadsUoLoas 

# xoQDes 03 # E7Xq QreEATOD 03 AuNOD azTUS: 6 nda LAInsogs 
zojoes zed sezfq #:/ ZIsg nda aoLoas 

>>>> ysTpurez Jo ezts ebueyo 03 SIHL ebueyd >>>>/ oF nda SHOWULIOUTEWON 
squeqsuoo eseg ---?: 


zey6ty LON ‘g weqzo eze seoTtaeq: 0 nda Taddo0udAn 
o06$ 063 AZISHOWLSOOUdAN 


@3BETD TITM em ssenord eyQA z0z Aqyxotazad pue ezts yorqs ---/ 


T Zt ATTeoyqeuoqne yt od 

0 JF pueumoo ,,juUNoW, E42 FATA ATOM 

epoo jydnazejut exXesy eEeTQeUe OF x, SACTIBY 
*eQex pneq eyqQ Wes 

o3 wezford [euturey e& un 03 peeSeuU TTTM nox 
iqtT-Suqep yaTA yUTT ysnu nok oO < ZI = 
peztsep osut buyShnqep zo qunoue Aztoeds 0 00% TRAST OANI 


0 nda LNQONOLOAY 
T “as LdOWALNI « 


BR es 


0 = edkywengng 

= szesyng 

et = TAouStH / 0 = TADMOT 
O = SAPeTIEQUI 

t= peaAressy 

OT = XOeILASTGsyOoT 

T= seoeszizns 

° seta 

€ aFun 

edTASpP *aepurer eoTaeqg 


0 = edfkyuwensng 

T = szeszng 

et = TAoubtH / 0 = TADMoT 
0 = eaeeTIERUL 

I = pearesoy 

OT = yOeALTeasyoota 

T= seoezins 

o= sbetg 

z= Fun 

S@oTASp ASpurerT = ODTACG 


weqskseTttsyysez:T = weqsksetta 
000b = eZTSxORIS 
Toesappyxo0 = edALsoq 

0 = edd«ywepsng 

T- = S®8AqSTS 

Z = peazescoy 

o= sbheta 

OT = yOeALTegGsyooTE 

I = szezsng 

T= seoezins 

pt = TAoubtH / o = TADMOT 


T= a3tun 


eoTAep Aepurer = edTAeg 
we qskseTts3sez:T = weqsksottg 
000 = ezTSsxDe AS 

TOESappyxo = edAzsog 

o = edxjweysng 

T- = DeAqeTD 

Z = peazresoy 

o= sbeta 

OT = yoerLTeGsyoOoTEA 

T = szesyng 

T= seoeyans 

vt = TAoubty / 0 = TAkoMoT 

o= fun 

eDTaepaepurez = eDTAeg 


* 


; Devices 


suotjdo euy3-eTquessy ---/ saa ,Add}z,, oureu :03 eatzp jewros 
ast Tqunou-aepAu worz :oF Zunow 


ARBRE BERRA MRA EERE EERE MMAR EERE BEARER RMN RRR ERE ‘SAI UT ST ,SeoFASp*aepurez, erNs SxeuU: 


* 
SOFAep Astpuer uoy7zeTtexs TOZF suoyzAezeloep Teuzre7zxe -- F°aopuer , : SeATIpuer 
* weqsks eTTd 3seq eyR Sutqqeuzoz ueym Betsy sag oyQ osn 


FRR B EMER RARER RARER ERR MRE ERE RERE REE EE REE ERNE MRR ERM ER EERE 03 drns eG “pEeqzEMTOZ eq Asnu seAtTIp eyQ ‘Hut juNoU rz0qSYv 


* 
esn TefoOTemMOD-uou rox pequezH uotsstured » 

“peazesez sqy6txz TTw ‘our ebsuy ezopoumon ‘9g6t (5) aabrxkdoo » 
* 

» *‘zeatip xstpuez etdues ey Bbuyqunow ATTenuew roy ystTQuNoW 


PRERREMERERR EERE EERE REE ERE AMER RRR REMEBER REE ERE R ERE 


rAepwel 1SI]JUNOW-AapWes 


*“(sao) weqsks eTtzF pto ey3 z0oz dnjes eze :¢sg pue :7Zs 
“(saa) weqsks eTtz asezy ETA CYR TOF dn Jes OTe 2 Ta pue Od 


KER KEK KKK KKK KKK 


* 
aN 





558 ROM Kernel Reference Manual 


0 

° 
ot 
ZA 


a\pue 

as ‘o# 

TW/ovw/Td/od’+ (as) 

qwg4ngy 

sbze 03 3utod: Tw’ (dS) ved 

Huypzys yeuroz oFQeQS 03 QUTOa! ow’ (od) 9\Ssur 
(as) -‘Ta/0d/T¥/ow 

(Da) owensAsqns 


T\-THAZT OJNI 


Hsu‘TeaeT » OxoW :OSWLad 
aun amax 


*spueumoo Sut qqeur0s ¢ eTAas-sQuTId Dp eqetrdozadde ey Bbutppe 
pue yoreqs oy wo weyq Sutysnd Aq 3no pequtrd eq ued srejeuereg 


<,POTTED 2Q7Ul/s8%,>‘0E  OSWINd 


tos se pesq ‘“pneq 0096 3e 310d TeTzes eyQ of efessou e Ang 


BR re 


eg WONG 
a T\OAT Imax 
OAT 43 3nOYATM eoueZesez AzezqyT e eutzep ¢‘ OuoWN 


= WANg 
= (9W) T\OAT usc 
OAT ees 09 butaey qnoyqTa gy eta AzexqtT & TTeD ¢ OWN 


WaNa 
gv‘+(a4s) T° SAoW 
(9) T\OAT usc 
ov‘2\ T'SAOW 
(as)-’9W ‘T° ZAOW 
OYOWW SASUNIT 


OAT © 90s 09 BHButaey Qnoyaqtm AzezqttT e oj yUTT / 


WANG 

4°sa 

weerqys epop ubftTe prom : OUuoW 

WAN 

T\ o\'so@ 

OdOWN 

WaNga 

(,8°, S@ yous) oxzoeuw eyQ UO pesn uoTsueqxe eyQ st O\! T\ O\'DDEd 
OO 


CO ren Perera 


° 
| 


WON 

T\‘o#  SaAOW 
00089 uo zeqstbez q © zeeTo 03 Aem yotnb: OYOWN 8 wWaTIO 
MR RE ME REE RE RE OE IEE RE AE REO EE OR UE RE UR I IE RE I OEE RE OR IE OE IE I 


eotaeg 3 AzexzqtT etdues ezopoumoy eyq Aq pesn 
seutqnoz yzoddns Atquesse TeaeT MOT wopuex -- t-ddnsuse 


Osh TeToOTeumoD-uou z0zF pequexrh uotsstwireg 
*peazesez sqy6tz Tty “our ebtuy ezopoumop ‘sg6t (dD) aubtszkdop 


ME EE EE MR BB RE EM MB I A 


WANG 
0’ ,e2>Taep*aepuez,  'Od 
OYOWWN  SWYNARGAN 


z@‘aqaddoLs‘NdN 8 J@adLId 
peddo3s yfun z0z 3ATq eAeQs ‘ 


Foezts 3Tunsedhy Taqv1 
AZIsWWwa ‘NWa Npu LoNLs 
Dang 

uBStte pzombuotT! _ tTped_npu aaomn 

eaznqonzyzs ydnzzequr : @ZIs SI‘st npu yonuLs 

Tdnws3INI dal 

adnzzequt uo sqtq eseyq Teubts 4senSts_npur SNOTN 

4seq AStP TOF (GOL) ASOTA TorQUOD yseL @ZIS OL‘qo3_npu = LoNULS 
AZISMOVLSOONdAW‘'AOeAS_Npul =LoNULs 

soTAeqd npu ULdw 
ipeubtTe pzombuoT mon: 
arabts_npu aLxEn 

= UMNITUA Apu aLxan 
spzombuot # ppo! aZIS LINA’3tunsedkw TanLOAULs 


ASTP SeVFeTHUTSs OF pesn Wwe - 


a 
‘ 


sqdnzzequt rox peqeootte atq Teubts / 


zoezts seqdkn = THEWT 
vseSLINOWON GW‘S3TUN_pu LONULS 
pzeoq uotsuedxe s,eoTaep sty JO ssezppe eseg ¢ eseg_pu SNOTO 
astibes_ pu ONO 
atisks pur SNOTN 
peubtTe pzombuoT mou! 
Tped_ pu aLxan 
a sbeta pu = aLAaA 
@ZIs @IT‘aeqtw TanLoAULs 


v O03 SLINOWON GW 
eoTASp sTYQ UT Ssqtun FO Tequmu umuTxeu /‘ 


ernqonzys styq Fo ezts / yoezts upw 

.OAWE, Sureu zeTpuey eTTZ sod ‘ g ‘eueNp_upur 

sxzezgnq soaebtuy zoz Azoueu zo eddy / edAyznqueuw_upur 

szezgnq Fo requmu / sxzezsngumu_upu 

zeputTho zeddn / TAozeddn upu 

zeputTks z9emotT / TKoMoT_upur 

eaeeTrequyT / SAReTIOQUT UpU 

pesnun { oezerd upu 

iT 3s88eT 3e eq LSAW -- SYOOTC peazesexz : sxT@ser_upur 

yoezq zed soes : YORILATA_upur 

pesnun -- yooTq TeoTHot zed soes / xTareaqsoes_upu 

seoeyains Jo zequmu / speoyumu_upur 

pesnun -- utbtzr0 zojDes / 62r9Des_upu 

xCoTd eB ut spzomBbuoT # ? yoTEezTs_upur 

ezts quewuortaug / ezTSeTqez _upu 

sBHeTtz sotaequedo / sHeTz_upur 

zequmu 3Tun / atun upu 

eueu TEATIP SDTASp OF TEeQUTO, / eureNDexe_upw 

eweu TeTpueY STTF Sod OF zSeQUTOg / SUeNsop upu 
0‘34%d°PONSOa@aW TAINLONALS 


rAopuled 





Example Device 559 


NOISUZA_LY 3LAGO 

(.t9FUr, ees-oTbeu) SOVIA_1Y FJLAaO 
(qunY stqZ FO pue OL) aINSGNA_JY uULay 
(zequtod yoeq) OWLHOLWA_LY ULav 
(@FYOoo oTFbewW) GEOMHOLYN Da ayomo 

o’LaY TuaLooNULs : 


NOISUaA a‘od 
GLINIOLAY aL aoa 
spoopug T'oa 
dyzoseqq3tut Toa 
CAOMHOLYN OLE ‘od 


PR 


idtzoseqqatut 


0 nda Taddan 


we sks ey ut shequozr reqjo ey A Fe YOOT 03 {ORM 
wory ,spou,, esq ‘“suozr eyQ Bbutaznbyzuoo z0z pesn st prety Idd LY eu 
“orez Re 3T eaeeT ptnoys pue AqtTzotzd e peeu you TTTM eTdoed json 


“(**twozz noX Butuunz 47eA4s 03 ezeym se yons) nod Anoge 
squeqsuoo oTbeu zeaocos}tp oF erzngqonzAs STYQ TOJ peuueds eq TITM ebeuy xstp 
eq ‘xASTpP worz ut 3ybnozq st reatzp znok z0eqzw ‘erzngjonz3s Hequwozr yw 


Sqr 
op ‘T-# beaou 


2 sseIppYasszta 


-(eotTaep e se noX Sutpeot 
JO peeqsut) wezhbozd e se noX unz 03 petiq SsuceUOS eseDdD UT 
ZOTTSO US UANASET PTNoYs sSTYL “UOTREDOT ETQeAnoexS YAsAzTF eUuL 


‘ 
‘ 
4 
4 


T' seTqe/Dexe worsy or0eW! 


Kxzezqy{"2exe woxrz uoy3ounsz Adoo peztutado AtyStH! yzorndureyAdoD arm 
eponscappy «aITX 
SponsogexeN aX 
buyputayuezznj7e5 «= EI'TX 
FzrayseLzes = CITX 
Teubtsoolty IX 
qzoadatem = = GI'TX 

aremM = aI'T™X 

Bewne> = a'IX 

Teubts aIiXx 

bewktdey aIix 

ysejwey = gIIx 

Bewand = aITx 

ASeLPPY aITX 

WeNOOTTY aITX 

qzoappy = GITX 

eACUeYy ar Tx 

weyeezz aliXx 

3etw = aIIx 
AzexqrTssotD «=«-« aI'TX 
Azezqyquedo = IK 
qonzysatul 86 aITX 

buqeq = aIx 

ZTOATSS QUT WEY arm™ 
zeareszuIppy dIIX 

qtt’ ebyue wory UF SOAT eseyqy Tina: 


ZEATIP STYR TOF spreog Fo AstT 30H 03 osy! 


Or3z0qN 
orutbeg 
ouren Au 
TION 
ebundxg 
S80TD 
uedo 
3FaL 


WSPB*9DIASP'ASPWeI 


etatsta ATTeqoTth weyQ eaey of szebhngep 
euos sdjTey At 3nq ‘Teuzeqxe eq OF eEARY 3,U0p ssouL 


eseq AzerzqtT“ sexe 03 requTod eyQA Jo uot AeDOT agntTosqy!: py nbe asyvaoaxasay 


LSIT 

Oana 

nt" sherhTzZuoo/setxeIQTT,, SpnpTouT 
nt sreabTyuoo/sep~rezqTT,, SpNTOuT 
wT uoTsuedxe/seTzeIqyT, SpNToutT 
LNOQOWOLAY JNAI 


uF} Aepurez,, SpNTOUT 
Axzezqy{ zoz pesn se oues ‘t°ddnsuse pzepueqs/ ,,t°ddnsuse,, epntout 


uF SQtqqut/ezempzey,, epnTout 
uF SYSEQ/Dexe,, OPNTOUT 
n¥°STOITO/DNSxe,, EpNTOUT 

nF SOTQe/Dexe,, OpNToOUT 

nF °OT/Dexe, SpntTout 

uF QUepTsez/oexe,, EpnToUT 

nt Axroureu/ooxe,, epnpTout 

uF SIOZTTETATUT/Sexe,, SpnTouT 
nF SODTASp/Dexe,, EPNTOUT 

wt sedkQ/oexe,, epntout 
LSI'TON 


woF_Aoes{zsItzy NOILOIS 


MERE ERMA ERNE RARER MERE EERE RARER ERR REEMA REE RRR REE ER EH 
*Azowew ut azeT TIT3s eseq Azexzqty ‘sTtez LINIOLAY did JI : sing 


edeg onozrewy wory XTF dOLS/LYWLS 68/7Z/Z0 
shuyuxzem ¥ SUOTREOTFFISTO erow weagy 68/T0/Z0 
* SUOTIEOTSTALTO STOW 88/Z0/TT 
eseeTezr meu TOF AATqQSEN eokzg Aq pesztedey g8/8Z/60 
aepuez peueuez ‘xeuddeyos “5 Aq peTtsTPON 88/Z0/Z0 
"ysTp eB eqetTnutTs 03 NYU Butsn 
eryaep AsTp eTduys e eq oj uosyoTzg eeT Aq PEeTSTPOW 98/L0/0T 
wse"aopAu uo peseg 


oouoDe jen pue AdWO UTM pe zseL 


*“seoznosez ezempzey Fo uop_ezyyTqze moys jou seop eTdurexe styL 

‘pezeys ATeezz eq ued wex ‘syseqy eTdtytnu Aq pezeys eq oj peou Aeuw 
3ey3 szeqstbez ezempzey so jes eThuts e& exTTIUN “YASTp wexr eTduys e 

zoF pepeeu ATTenqo0e jou st yxseQ e yYSnoyQ ‘yseQ | sepntoUT eTdurexe stTyL 


*KTq0eatp 3 Adod o3 Quem 3,uU0p 

Atqeqozd nok ‘pro 3eymeulos st epod sty, “erTeYMESsTS puNOZ Jou uvoTReuUTOsUT 
SUTEQUOD QI “STEQTIM ASeATIP eDTAep roz Hhutpeez pexztnbex st epoo stTyL 
‘ueqsks eTTd 362i SYR UTM SYTOM “ANOYRTA pesn TO 

‘eoTAep AOTS uoTsuedxe ue 07 punog eq ued 3eY4R YseTpueT ATUN p eTdues v 


*Bpod SDrTASpP UOC_SeTSeXS -- use“ Aopurer 


RR KKK KKK KKK KKK KKK KKK RK KKK KK 


MERE MERE REE EEERE RRR R ERE R ME MA EERE R RE RE MERE MA RE RE RENEE EEE EEE 
*” 
*esn TeTorTeumoo-uouw TOF pequesr6 uwotssTured * 
*peazesez sqyhtz TIv ‘our ebtwy ezopoumon 6e6t‘ss6T‘986T (D5) aubtzAdop 
* 
EMRE ARBRE MBAR BREEAM RAE ERE REMAN R AER 


WSe sdIAap AOpwes 





vices 


De 


560 ROM Kernel Reference Manual 





“auoot s,XSATIP STYR JO SAAALIOOL ©43 UF PTSFF un=LOAGOUd, SAF UT pets foeds 
eq ysnu preog znok zo xequmu jonpord peubtese ebyuy-exropoumo) eqL 
‘ZeATIP STU seyoREM ZeYR preCg e spUTF STEATIGpuUTE UeYyA peTTeo eq pue 
‘zemexp uotTsuedxe ey3 Ut reATIP sty and pTNom nod ‘pzeoq uotsuedxe ue 

©3 pet} Sq OF SEM TEATIP STYR FI “FINQS HSTzZuopo{ny ey sqTeys Sr0H 






KeRERE KEE 


MRR A EE IIE A EI EOE EEO EO EEE EE EE EE OR 
ZNOOMOLOY ANJALI. 





(se) astIbes pu’oe TT" eacu 
(ast1Tbes eq) epod pepeoT zno oF zequtod eaes ------? 


9e’y [T'eaow weYA sseDce T6Eeqses! (se)arrsks pu’9e T"eacu 
Dexe oj requtod e eaes ------: 





se‘op 
szeqstbexr petytpow Tiw earesezg ¢ (ds)-‘ge-9e8/LPp-Tp TT" weaou 
<,PETTeS :3FUI/se%,>’S  OSKINd 

xeqstbex y ZueTueATOD e ojUT TeqUTOd eDTaep eyQ 306 ------- 

FS OUFANOAITUT 

eseq vexg -- 98 

zequtod estaep -- ge 

eseq Azexqt{T uoypsuedzg -- ye 
wea Azexodue of squtod 


ebesp zeqstbey 


. 





*moTeq ,uedo, 
ZoZ uocp3dtz9sep ey peex eseetd ‘oexe xq pepeerzy3-eTbuts st TTS stun 


‘uopqoe zozy Apeox st AF TEQFE TFQUN ASTT SYR OF SOTFASP 
anoX ppe 3,u0p st uopqantos Asee eq, “TeIeF eq VOU Asn sTyL “SeoTAep 
anoX zo ebundxe ue Sutpntout **-ebundxg ue esned ued Xzoweu butAesctte 
3eq3 xequeuez ‘uofqounz uedo aznoX uy Azowew eReDoTTe noX jr *3eeaeD 
TeucTATppe we st ezeyqQ ‘ernzees ,LINIOLAY did. S43 osn 3,u0p nok ZI 

2 INWLYOdNI 


*pepeoTun eq TTTM 
e@DTASp eYR UeEYZ “TION surNjeI AF FI “ASTI SOTASP eYR OUT 
PSEXUTT Sq TIFM SoTaep 943 UeYyR ‘zejuTOd epTaep eYR sUIN_eT At FI 
‘Oe UT ST 3STT quembes sodebtuy eyL “Od UT st TeqUTOd eDTASP OTL 
“peqesoTTe ue6eq sey ertaep eyR zeAzZe peTTeo syeh eutyqnor sTyL 
ILINIOLAY abd wos 





2------- +--+ -- $$ $n nnn nner eutqnoyyzuy --------! 





ASTT eqeufure3/ Oo Mod 
Huyzaspt ‘ONIULSAI_GIT ONOTLINI 
NOISIASY‘NOISIATA GIT CuxOMLINI 

_ NOISUSA‘NOISUZA_GIT GyOMLINI 

CaONVHD JEITiGSSONNS AGIT‘SOWLA GIT ALAGLINI 

ewenAu’SAYN_NTI SNOTLINI 

@OIARG IN‘S4AL NI 3LAGLINI 

TOTIELEIEP 


i3axZ NT eq 3sny! 


peqeuymre; TInu st eTqez euL: 

“TTe> 3eq3 UF and of enTea eGR st Queumdhze pucDces eUL *Buol/pz0m/ezkq! 
STIR XOJ Eseq EDTAEpP eYR Wors JeszZO OY ST Queumbze AsITF SUL: 

“,F  STOZFTETAFUT/oexze, STTF SCY UF STS sozoeU SNO'LLINI /CHOMLINI/ALAGLINI ‘ 
ey, ‘sebed Tenuem s,euTqnox WONTASzTUL/oexe uy peTsToeds: 

St AeUTOT OYL “serNQONIAS SREP OTAEAS SOZTTETITUT STIS e3ep UL: 


Wise -eolhep Aopues 


4 


xeyxzeu pue eTqeyZ uof_ounyZ ------! 


quoF {oun 
waoFjQoung 
suoyjOUNsZ pepueqxe wo AsnD 


oraroqu 
oruybeq 
suoTatutsep eotaep Au 


erzngny zoz peazesoy! TION 
ebfundzg 
esoTO 
uedo 
seutqnoz weqshs pzepueqs 


euTq{NoUyTUry 
eTqeLeqep 
eTqegouny 
yoezts aeqhw 


unz 03 euTqnoz 

SIOZTTETATUF SAep OF rEeQUTOd 
SIOZTIETITFUT WoTQoOUNZ 0} reqQUTod 
ezts eveds ejep 


= *unz 03 eufqnox e 03 AuTod prnom 

LINI LX weyR es jou sem 3Tq LINIOLAY ©49 JI “MOTEq SeTqe 
eseyR FO eUO OF squTod zequeu erN_ONTAs LINI TY Sy3 3eW3 
sueeu styL “»LINIOLOWY ald, STEM eM ZeUR petzToeds Hejuozr eqs 


Carrs 


o 6A SP 
queuubtTe prom eor0sx : 


o‘ot‘et’,(T6°8°8z) T° Le Aepuer, q°op :Butzaspt 
<TInu>/<zT>‘<zo>/’, (AX-u'p) wopsfaex"uotsrea eweu, ST ZeUIOy ¢ 
eotaep eq butqroddns ut dtey 03 bey zeTsZTAUepT ue st STU 


s 


T nda *NOISTAZa 

“st ATTeez 3eq3 

eptaep yOTYM Fo uoTysenb e zeseu st ez0eq Aem 3eUL *eTTduopez I 
euy} yore Tequmu uoTsTAez ey} seoueape jeYR AdyrOs e esn I “SDTASP 
eq3 ut satq eyy Aztjuepy Atenbyun ptnoys styL “woTtsTaex; zetnotaazed vw 


Pars 


Le nda -NOISUTA 
2 


*-zequmu uotszea xofeu e ? 


Oana 
euey AzexqytT uotsuedxg /‘ o/ ,AzezqtT“uotsuedxe, q-op eUeNQT IX 
INONOWOLOY NIT 


ONYNATAIAN : ewenAu 
a 


SCARY TITM eDTASp eyR 3eYR eueU ey st sty ¢ 


Oana 
0‘, Aepuex,, q°op 
_ iewensAgqns 
TrTe 3e petqeue BGuyHSnqep Aue 51’ THART OANI FNAL 
esn BbutbhSnqep z0F eweu sTyL: 


azis iui Taawi ‘ 
QtUL 
S5uzz3aspt 
ourey Aur 
radan 


@OIAad IN 


LINI_GY wala 

(Buyzas 3x03) ONIULSGI_IU way 
(eweu oexe) WAVN_IY ULdy 
Tdq_ta aLAa 


FdAL LU ALAA 


Pe ee ey 


(qDdezz0D eq ysnu) 


wise-eodlAep Aopulel 





: Source Code 561 


IFF Specification 


‘weyQ ut Huot 003 eyeR Jou prnoys em / (4TuITEegG/pTqzog eTA) 
seUT_NOT eseyy ut eTTYyM Hbutyoqtms yseQ FO peurny sey oexe eDuUTS 


jezes eyeL 

‘eutT3 Sues 043 2e epos ebundxg/esoto/uedo xnof xzeque 03 efeueu 

aybyu yseq reyjo euos ‘uexorq st ()PTqTOZ ey2 FI * ()PFQTOg OR 
Yeoerq TIT* ()3FeM AOeSeTTPUT TO QoerTp e sesneo AeYyQ ebundxg/esoTD/uedo 
aznoX eptsut butyqqAuy ‘efueyd TITM styq eoueyo pooh e st ezeqL 
*»PTqQI0, seaToAuT poyjeu Sutpeezyz-eThuts eyQ ‘PE/EEA ITEASYOTM TOG 


‘outa e& 3e ebundxg/esoto/uedo znoXk eqnoexe TTT# 
yseq euo ATuo ‘/pepeezy3j-eThuys eq of peequezend ere s{TTeo eseyL 
+ LNWLYOdNI 


"sn roxy 9e ut zequtod eotaep azno 3nd Apeeazte sey oexg 

* (eBundxg/esoTo/uedo) seutqnoz HbutmoTToy ey OF TTeD & OF7UT 
pezetsuez3 sqe6 AtTenqueae styA ‘eoTAequey/entTaeqesoTp/eotTaequedo 
STTeS Tesn oyy wseym ‘“spueuMI0D sDezzequT we sts ey sutbeq ezeH 


S®-08/LP-TP‘+(ds) T*weaow 


BR ee te Ok ek oe re re re ee ek ee 


:Z0TIG ATUL 


op‘se T° eacu 


OaNa 


HEEB RBBB ARERR EM BRM BEBE RE RRA MMERR EERE EN 


‘owep sty3 BSuyuunz weym peTTeqsut 

QI zezmnzoeznuew zeTnoTAzed Aue yATM pzecog e eaey ATTenQoe nok 
ATOxTTUN st Ay eoUTsS ‘owep sty Aoz yeyR Hutop jou w,T 3nq 
‘peTTEZ wuoTAeZTTETATUT znoA FT TION & OF OP Jes ATTewTOU pTNom nox 


AxezqyTesotd sxSTTIWo 
AxexzqtTt uoypsuedxe esoTD MON / Te ‘ye T° Saou 


* 


:pugz 3TUr 


weyeeTA SASTIVO 
OP ‘FoeztS upu# T° eAocu 
we qsks 02 KYY UInQey / Te‘ee T° Saou 


PETTEASUT satun Tre TFRun dooT / doota s*sTq 
9P‘SLINOWON CNH q° dup 
xequmu 3tun dumg / 9P‘T# bppe 


~, ‘yseq zeTpueq ey Jo T3zaGbes ey y UT 
Ut PETITE st astibes up 5st ATuo 3nq ‘yI0M TTTM DOUdLUVLS ANGY 


pe‘SPpONSCGPPYOAT  dI'DINIT 
ezey Ut ozez e& ssed 03 YO 8,31: 
TP ‘DOUdLYWLS aNav# tT beaou 
TP‘o# T'beacu 

0 03 Aqtxzotzd eataep es op‘o# tT besouw 
ssezppe Eeponectaep 3°65 oe ‘op T° eaou 
é3eqM of Ang ‘TFeZ ued sta: 
pe ‘EponNsogdexeNoAT aI DINIT 
oe ’ece T° eaow 


MOTeq ej0u ees / 


seangonz3s sodebtuw prtng 


WSeBsdIASp ASPWPI 


“jou seop eTduexe styL “WOTSTTTOD eureu © esned oF Qnoge ere j 
nod 3st yooyo ATTeexz prnoys nok ‘Ast T sop ey A og Hbutppe ezozeg j 


queuucrztTaAue ut # QATun ez0ASg / (€®) 3¢un_upur‘gp T° Saou 
sueu ut ez0Qs pue £ (€e) Z+eueNp upu‘op q°eaou 

T snutw ‘ITOsY exen - op ‘oes# q°ppe 

zegqumu 3Tun 3e5 : op ‘9p q" eno 


:doota 


WOANLINN s3yun TTe ynoqe soaebruw T1393 MON : oP ‘o# beaouw 


(€e) oweNsop upu’oe T°’ =aou 
oe’ (ge) ouwenp upu eeT 


QuewuorztTaue ut eves pue 
eweu eptaeg FO zppe 425 


qenz34s3tUI = SASTTWO 

Tw’ (od) ayur upur T° eet 

QT Ozez-ez 03 peseu 4,uU0q : OP ‘o# tT beaou 
; 


SZTTeTaTUT of Azourweu oq AuTod : ze ‘op 
qeyoed so uotqzod queqsuom eyQ ezTTeTATUT OF AoONTASATUI esH 


T° eaour 


SxSTIWO 
T’ eaow 


‘ezey pexoeyo Jou Tore weyPOTTW :5nG:/ ee ‘op 
WeHOOTTY 
qeyoed zeqeuezed uno xzoz wooxz ybnoug ‘_ op‘szoezts upuy# 


Tp‘OITadnd ANANiUVaATO ANGN#F 
qexoed zejeuezed oponsogexeW PTTNq o2 Wwu Azezodurey eAeSCTTY 


sepou sod se syrun jii 
ey 3 Qunou ues nod ‘peznhtzuom AtTnzsseoons sem pred aznod JI iii 


*peqzeqs 
@ze OM TEASUEYM sqTUN INO FO F TTS WUNOU [T,OM ‘“AuNoU osn 
03 Burpeeu 3noy3TM 3sTT §,sop 03 shutyz sppe TTeD SpoNsoapPpY SUL 


*szejeuezed eqetxrdozdde ey epoo pzey Atdurs [TtM em ‘eTdurexe sty 707 
‘eotaep Teotskyd etbuts ey uo suofTatqzed eTdtarnu roxy eq pTNoD 4T 
‘qunow se qsnc “ZJTEsS{T ASTP ey worzz yybFr uopyewxosutT styy 306 
AtjTengqoe 03 Tnzesn eq Ayhtw AT ‘sSYsTP TOG “pTNom eoypaep sTyA FO 
puemros ,qunouw, e se esodind ewes ey3 seazes styz ‘“soaebtuy oj ssed 
03 ASTP Ano FO soTAsTzreQDereYS eR Hbuyqtrosep yeyoed e pT}nq em ereH 


q°2T°q 
T" eaou 
T" eaou 
SsNLAd 


pernbyzuop se pzeoq y2eW / (OY) SHETA PO’EHDIGNOD Gao# 
ssezppe eseq pxreoq eaes : (cy) eseq pu’ (OW) IPpYPzeOE po 
ssezppe ezngonz3s Byyuop AVeH : ow’oa 
<,ozez-uou peurnjzez ButputgyuerznDpAeyH =: ATUI/sy,>‘OT 
Zeaytzp peoTun pue 3TxXg pug 3tur beq 

punoy jou rAeTTOTAQUOCD FI _oa T°383 

QsTT FO yreQs QED : oa’ (sy)eseg pu T° saow 

pw ‘butputaquezrnD3eD0AT aI TDINIT 

(seqiq p = yqbuetT) ssezppe 306 asne / od‘ v# beaouw 
sbuyputg quezimnD ey} 36D ow’ (sv)eseg pu eT 

€a‘o# beaouw 

(pw 03 esequotsuedxe] / py‘oda T° eacu 


isseoonsdo atut ------/ 


4 
s 


XOITY FUL beq 
oa T° 382 
Azezqyquedg = SASTIWO 
oa‘o# tT beaou 

Ty ‘OureNqTIxg T eet 


Azexzqtt uotsuedxe eyQ uedo / 


euweu “qtT uotsuedxe 305 / 


* 
*pzeoq (3szyz) aznoXk surnjez ()Sbuyputaquezznpy4ey » 


wise-adiAep Aopulel 


rare 


Oe te ek et re ek ew ew ok 





vices 


: De 


562 ROM Kernel Reference Manual. 


<,peTtes :ebundzg/s%,>‘0T  OSNLOd 
( 9e :eptaep ) / :ebundxg 


youezos - Tv-OW/Td-0d 
(qoqezos) eseq Axexzqrt - ow 


“eqeTdmos 03 euyty Huot eye esTATeyRO ZO ()3TEM UBAN Aeu Qt ‘xoQeDOCTTe 
Kxowew eyA worz peTTeo st ebundxg esneoeq :ej0ou Queqiodmy zeyqjo eup 


“TTON uznAez pue Hertz ebundxe peXejtep 

eqa yes Kew efundxg estazey30 «6° (3TUI 03 WeaATH se) AsTT JAueubes 

eq uznqez Aew ebundxg ueyq3 uedo zeHuoT ou st eoyaep eYyA JI ‘“ouTQnoz 
efundxg eyA worz peurznjez eq ayStu 3eq3 sbutqQ AuezezszTp omy ore Or0NL 


- Xzoweuw 
uo MoT st weqsks ey ueqm zoqeVooTTe Azowew eqq Aq petTeo st ebundxg 


Peer er en Ten Tn TO eR Te OTe TO Ten anrS 


iiiast beg eqQ x0 ozez reyqATe uwznjQez LsAW: 
€e-ze/tp’+(de) TT" weaow 
ipug Ss50TS 


ebundsg 
efundze eq op 


= pug_esoTo 
(9e) sbetg pu‘axaTaq aari# 
Sutpued efbundxe peXetep e eaey OM ZT OOS 


pug escto 
uedo sn yata azeT euckue st exeyqQR JT ees 


(92) ZNONEdO GIT‘ T# 
szeuedo xemez euo HButaeyq se sn yreU ------ 
op avwato 


:80FAeq SSOTD 


4 


atunebundxg asq 
eDtAeg SS0TD ss" euq 
seofaep , Teer, JO sTEATIp r0Z pesn eq jiiiii‘ 
PInom 3I ‘ezey peddtys eq TIT 3TUunebundxg ‘suedo ueemjzeq reeddestp 
03 sqUeqQUOD eYA QUEM 4,U0p eM pue) ASTP WHA © ST eTduexe styQ eDUTS jiiiiii- 


(€®) BNONZGO LINA’T# bans 
esn Ut TTT3S Sf 3TUN eYA FT cos : 


jij jeenbeyorl sty 3e eMODTeEM Jou szeUIORSND: (ze) 3oTAaG_OL ‘oP 
“**pesoTS ez ,em: (Z®) LINA Or ‘oP 
op ‘T-# T 
uopqadnizos eTAqns e ueYyA 70Q3eq ST YOTYM) 3TeY AT3e ;peumnt 
TIM ydueajze ()orutbeq Aue ‘TOIAad OI UT T- & T3TH 
ufebe pesn jou st ysenbeyor ey 3 emns eye * INYLYOdNI 
ee’ (ze) ZINA OL 
ze ‘te T°" acu 
<,/PETTES :e80TD/S%,>‘0%  OSWINd 
(ds)-‘ge-ze/Tp T*weacu 
( Te:qot ‘9ge:enTaep ) /: 1850TO 


“TINN UINZEeT LSOW PSOTSO estmzeq_O * (ATU Of UeATS se) AsTT Queubes eqQ ¢ 


WSB*SDIASp ASPWeI 





winjex Asn esoTD uSEeYqA ‘pepeoTuNn eq 03 SENSTM EDTASP EYQ JI “SUT ANoT 
@80TD EGR WoTZ peurnjex eq 4y4htTu Aeq3 shutyQ AuereZZTp OMA ere oreUL 


pug uedo s"ezq 
i <,peTtey :uedo/s¢,>'Z  OSWINd 
eazntyey uedo wo AOIARG OI yserQ : LNVLYOANT! (ze) aoTAaG_OI‘op T° eacu 
(ze)uomig OT‘op q°eacm 
OP ’TIIVANAdO WaaOI# beaou 
izozzq_uedo 
tzozzq ebuey uedo 


Example Device 563 


sqz 
pe/ee/ze/zp ‘+ (de) [T"weaow 
<|> wotqoeq01d ebundxe zo pug xx/ (98) LNONAdO GIT‘T# as*bans 


ipuq uedo 


nezeTdmos, se qasonbeyor AZM :LNVEMOMWI! (Ze) adkL NI‘OSWATGTY NH q*easow 
(ze)aowsa OT’0oPp dq eacu 
op 


(9e) sbeta pu’ axaTad aeIt# 
sebundxe peAetep juesaezd ------ 


(€®) LNONZdO LINO ‘T# 
(92) LNONadO GIT‘ TH 
zeuedo zeyjoue Suyaey se sn yrEW 


Sutdeexxyooq Teuzequr?/ 


(Z8) LING OL‘opP T*eaocu 
€e ut zequtod ytun / ee ‘op T' eacur 
ryoatug uedo 


zoxzxq uedo s*beq 
op’ (ve) 
MO PEZTTETATUT ATF FT oes 


ge:qutodaep zp:umuytun ee: yqojeros: atunatar 
afun e dn ernfuos pue Arq 


yoatug uedo 

op’ (pe) 

pe’ (T"op’9e)s3tuq pu 

op ‘z# 

zequmu 3tTun SAeSs = zP ‘op 
peztTTerqrar Xpeezte SF Qtun o4Q FT os 


(sHa) ebuexz Fo qno xzequmu Atun : zozzq ebuey uedo 
OP‘SLINOWON Gn# 
xix € 02:0 DINO xix ebuexz uy st requmu Qtun eYyy FF Ses 


qoft eq eves / ze’te 


(ds)-‘pe/ee/ze/zp TT weaocu 
<,PeTTes :uedo/s%,>‘0z2  OSWind 


<|> TTe> Fo uoTRZeInp azoxy xzeuedo ue eyez: (9®)GNONAdO AIT‘ T# a bppe 
*pebundxe 3e6 3ybtu eotaep ey ‘orez st LNONAdO AIT JI  “rOQDea obundxe xx: 
S,@O0FASP STYR OF TTED & esneD ued TTeS ()weyooTTy Aue tqutod eTaqns xy! 


( Tp:sbetzy ’op:umuqtun ‘Te:qot ‘ge:eotaep ) / ruedo 


_"SOIASA OI dn buy33es Jo ered seyeQ exe 
“sPpIeTZ BdXL NI PUS LINN OL eyQ dn yes ostTe pTnoys om 


‘TInJsseoons sem YF JI “TorTS we wo plets wowws OI eyR sqes uedo 


Wise adlAep AOpues 


<, 4883 ppe oF Jnogy/s%,>‘0€  OSWIAd 
op = wwalo 
(°'Q Fo ptr qeb 09 
at ()xse~uey om) ,surnjzez, Teas yseQ TT 
zoizze ssezppe ejezeuebh ee‘T- eet 
zeqjutod LINN earesezg (ds) -‘¢ee T° eaocu 
ze‘ (Da) utbeq xeeL eet 
Te’ (€e) qo npu eet 
yseq ey dnqzeqs 


_ o> Oana 
zeazes AdnzzequtT 03 2zppe qfun sseg ! (€e) WLvd SI+st npu‘¢ee T° eaou 
LdOWaLNI aar 


(noX zoz styqQ op ues?! 

() 320appw) ‘esn ezozeq weyQ uo oTbeu yr0Mm!/ 
BSIIMIN SAeY {LSA S3STT i DNYLYOdWI ->- oe ZLSIIMIN 
oF’ (€®) LSITIOSW dW POT 


s 


astt s,3z0d ebessow s,3yun ey EzTTeFATUy ------! 


Oana 
ds ‘g# Tt 'bppe 
</RTS=ASSQ /XTS =3TUN ‘QTuNATUI/ssz,>‘0€  OSWLAd 
(as) -‘ee T" eaou 
(as)-‘oe8 y"eaou 
O€-THART OANI 9541 
(€2)NSWLOIS GH’0e tT eaocu 
ge’ (ee) qo npur eeT 
(ee) OmadS OL+G99 npu‘oe TT" esocu 
(yOeQs uo pues) 324d qtun -- queumbhze : ee (ow) - ‘ee T° eaour 
(€®)usdands O1+G93 npu‘oe T°eacu 
yoreqs Fo pue qbty : oe ‘ (08) AZISHOWLSOOUdAN eeT 
(€2)UAIMOTdS OI+q09 npu’oe TT Sacu 
yoeqs Fo pue MoT / oe8’ (€e) yOeAs npu 
UOFASUTOFUT YORQS SYR SZTTETIATUL 


* (pepeezyy eTbuts euoseq of sty uo puedep oe 
-- sn z0z ()ptqzog e euop sey eotaequedo s ,5exe) 
4Tun eyQA uedo 03 petz3 esTe euceUOS JT ------ 
Ajseu Azea eq pTnom 37 :ezey deets 03 of Aouued oM 
‘dn af es 09 ebueyo e sey xyseQ MOU 
eYN3 TT3UN FYONSI Yd 03 320d efessou sty Aes OM 
-- ezey AOTTZ & Op OM “HXSeQ ATuUN eyQ dn AxreqQs ------ 


zequtod eotaep eztTeTyArut!: (€®) e>taeq_npu ‘ge T' eaow 
zequmu 4Tun ezTTeTITUT: (€e) wWaNITUQ npu’ zp q° Saou 


co ii INWLYOdNI ii! 
» GWG, IITOSW se orez jeszzo yrEW: (ce) WWa NPU‘OOPHTech#H T° eAacu 
ii BNWEYOMNI ii‘ 


(9e)qyIshg pur’jonz3saQTUI SASNNIT 

Tw‘ (od) q7ur apy T eet 

GINA yy Hbuzztpreyaruy st qonzysytur : ze‘ee T° esow 
A} ozez-ez OF pesu 4,uU0g / op’o# T'beaouw 


_ ee ‘op T'eaow 

pug 3TunItUL beq 

= op T° 383 

(9e)qTIsks pur‘weyOOTTY SASYNIT 
TP‘UWaTO AWENiOLTand ANaN# Teac 
oP ‘joezts atunaeqsn# T° Saou 


a 


Azowew qyun eyes0TTe ------! 


(ds)-‘ze/pp-zp T“weaour 


WSesdlASp"ASpwes 


<,/PETTED 2 3FuUNATUI/sy.>‘O€ SOSWLnd 
( rqadaep:9e ‘yoRezoOs:¢e ‘zequmu atun:zp ) / 24tuagtul 


EMRE EKER EMER HAMAS RAMEE ME EEE RRMA NERA ERR M MANA RRR MERE 


8qz 

eTqnog: op ‘op T° ppe 
iquofqoung 

sqa 

PPY: op ‘TP T’ppe 
rywuofqoung 
7 


suotqouny otsToOeds-eotaep ,butyjou op,, omn! 


, 
woysng -------/ 


“TION UINZSET LSAW UOTQOUNT TION, SUL! sqz 
op wwaTlo 
<, POTTED = TINN/S%,>‘T SOSNLAd 


9e/se/zp/tp‘+(ds) T"weaour 
tpug efundxg 


op‘zP = T "Saou 
enTea wrnqjezx ano dn yes ‘ 


weWeezq SASTTYO 

eeze ejep + suoTZOUNZ JO ezTs eReTNOTeD! op’ (se)azZISsoOd HII mM ppe 
suotqounz JO eseq eQeTNoOTeD: Te ‘op T°" eqns 

op’ (S®)azIsoaN GIT A*eAcu 

op awa'to 

eseqeotsaeg: te’se T° eaocur 


s 


(4ZISOIN AIT ¥ AZISSOd AIT worz eReTNoTes ysnu) Azoweuw mmo eexy ------: 


*-+'ezey sButsoto ofstoeds sotTaep 


(weyeezgy ez0seq) AsITy eaocuey: eacwey SASTIVO 
Te‘sge TT" eacw 


4 


ASTI eotaep worzzy yUTTun -----~! 


zp’ (ge) astibes pur T°" eaou 


Zp ut Ast{Tbes xzno ez0qg ‘sn Jo ptr 30h pue peoye of ------~-! 


pug ebundxg 

os = op 

(se) sheta puaxaiaa aari# 

Betz ebundxe peXetep sy3 jes ‘uedo TTT3s st 3T 


$Tt 
‘eTduexe z0zy ‘LYWIOA TEQFe peerZ eq O2 NWA OY Quem 4,UOCpP om 
eouts ‘ouep xSTP WWY STYR TOF YNo pequeumod st euTT HbutmoT[OF euL 
($®) LNONadO @IT 
uedo sn sey euoctue 5T Ses 


ge'(se)qtishs pu T-eacur 
ge’ge [T° eaour 
szeqstbez petstpow TIw eaes / (ds)-‘9e8/ge/zp/Tp T[*weaou 


wise adlAep AopweI 





Devices 


564 ROM Kernel Reference Manual 


esneod 3,UOp SUyTQ oes oYW 3e spuEUMIOD HbuTpues sysey OMA Os °° “pepeRezyy 
eTbuts seotaep buyyeu zo AqtTTqTsuodsez eyy ueath st ueqzo olutbeg 


-KTe,eptpewuut pesseoozd ro yseq ATuUn 
ey3 zoz dn penenb zeya3te st OL CYL ‘OF HSutwoout TTe sqzeqs olutbeg 


D0800000$ == nda 
qeuzog ‘eITIM ‘pecy 
jzeaezo0z Adnzzequt ey z0F ,,37eM, PTnom AeyA eouts 
‘sqdnazzequt Sutsn zt ,ATeqetpewmy,, SuCp eq YAN Ue spueuMIOD SseU] 
‘sqdnzzequt Bbutsn st / LdNWaLNI dal 


OTZEPS9 LE6WHOdAAOTZEPSOL86waodaa 


TILOOTTTTTITTOTITITTITTTTITTITITTIITTS nda 

‘spueumo> eseyy TOF peeyxeAO Yo RTMS yseR 

eya 306 3,u0m nok Kem styL ‘“pepntouy eze Auerqueez oOTs pue 

qzoys ATTeTAFIA STE AeYQ spueUMIOD TTY —‘“UOTSsIeEA eAEeUTERTe UY 

OTZEPSILSEWAOUAAOTZEPS9LB6WEOdas 

TIOOOOTTT00000000000000000000000% nda 

*yBnoue eq qou Aew yotyqm 

‘spueumos ofstoeds eotaep ze asn{ o 9 nok sqtutT poyjeu sty 3eq3 SION 


ysnta ‘qzeqg ‘dojasg ‘jesey ‘pTTeaul ere spueuMIOD eje}Tpeumy SUL 


(a0-ON) 

(a0-ON) 

(SWALNAN suznjey) 
(T suzn jeu) 
(GI‘TWANT) 
(AITWANT) 

(9 suznqjez) 

(9 suznqez) 

(9 surn jez) 
(a0-ON) 

_ (©3724 se cures) 
_dLa (a0-0N) 
aqua (a0-ON) 


ag 
dia (a0-ON) 
aig (a40-ON) 
aLa  (uoumon\/) 
(uoumioD /\) 


*(@TNpeyos s,TeTTeS eyQ uo) 
peTpuey eq pTNoys spueumIoD YqoTYM TTS OF pesn st 


INIGONWHOWGY_GL 
INIZONWHOCGY_GL 
SYOWALWONLD_dL 
FARLBATUALD_GL 
au 
avmimwa_aa 
SOIVISLOUd_GL 
ALVGSAONWHO_Gi 
WONSONYHO_di 
SAWS _GL 
LWR0g_dL 
MaaS_GL 
MOLOW GL 
HSO'TA_GWO 
TaWGS_aWo 
d40LS_qwo 
‘wWa'ID_GND 
aivadon_qwo 
aLTaM_qWo 
avau_awo 
Lasma_qWo 
GITWANI aWO 


XTe\ejpypeuuy 
euTsep stqy 


BR Re ee re re on ow on ow 


ipue eTqezpuD 


qurefueyqouey 
qurebueyoppy 
SYDeTLUMNISD 
edfkLeatza3e5 
OPTIMMEY 
peoymey 

sn qeqs org 
eqeqsebueyo 
umyebueyo 
eacueyAW 
3IMPu 

yoos 

TO ION 

qsnta 

4zeQs 
doqstn 
xeeTD 
eqepda 
32MPu 

qaMPU 
qosoukn 
PTTeaur 


00000z00$‘ 
00000T00$- 
00008000$- 
000080008: 
000020008: 
0000T000$ 
00080000$/ 
o0007r0000$s: 
000z0000$¢ 
000T0000$- 
00800000$‘ 
007000008: 
00z00000$? 
00TO0000$ ¢ 
080000008‘ 
070000008‘ 
0z000000$/ 
oToO0000$¢ 
80000000$/ 
¥0000000$- 
z0000000$: 
Tooo0000$ 


Tod 
Toda 
Tod 


BBBRARRRRRRRRABABAR 


RAAHAAAAAAAAAAAAAAAARA 


:eTqeypu 


*zequtod ,TeqetTooes, TTnu-uouw 
Ktqeqozad st 31 “eerze , TeqeTooes,, 
suo) «6 STYQ QueueTduyT o7 QUEM 
ZeaTAp & TEASEMOH “spueUMIOD Yous uO 


e yata pueumroo Aue joefexz 03 4s0q 
ey3 Fo HSutTpuey eyy st ensst uedo 
Aeu etpeu etqeaouez sjzoddns 3ey3 
eqezedo 03 osngzez ATeAezeqTTEp eM 


i285 ST 3tq CaeY (ALIYM GLE/GVAY GLa) spueumod ,pepueqzxe, ey :FLON 


WSeB*sdIASp*AOPweI 


‘pueumios eotAep eyQ QueuweTdut 


TTT* 7eYR eUTANOT eB FO ssezppe oy dn YooT o3 pesn st eTQEeQpUo 


suoftqQouny eotaep eyQ sutbeq ezey 


AMER EE ME RE MB HB BB RM MB RRR 


s32 
zp‘+(ds) T'eaou 
(T’@p/9e)sqtun pu TzTO 
zp ‘Z# 


SDTASP SYQ UT TORDeEA ATUN EYQ QNO zReTO 


37 os ‘ozez Jo AunoD 
eyes ST STYR MOUY OM 


atuneezg 
"eanqonaqs Atun syQ serz 


zp‘ (ee) UmMNATUA Npu q*encu 
zP 20 UWIO 
qzequmu 3fun eyW eves ------! 


(9e)qtIrshg pur‘yseLuey SASYNIT 

Te’ (ee)qoz npu = eeT 

‘esn ut jou ,peequezenb, st ------/ 
uedo ue sey 4tTun eYyA esneDveq ---~----!/ 


‘yseQ S,34FUN EY Z FO pT 30H 


zeazes 4dnizequt eyQ eAcUIeT MON 


(9®) qt1shg pu/zeazesqurwey SXSYNIT 


OP ‘SIuOd GINI# beaow 
Te‘ (ee) st npu TeeT 
LdOWaINI = aI 


ernqonazys ydnzzequt of AuTod / 


zeazes 3dnrzeqUyT s4y eacuez of requeuexz ysnu nod 
‘sqdnizzeqjut umo s,37 sey yTun yore pue ‘qTun nod ebundxe ues nod sr 


T°’ eaou 
SSWLAd 


(ds) -’zp 
<,peTTtes :qtunebundsg/s% ,>‘0OT 
( zqdentaep:ge ‘xgdgtun:¢ee ) / 


(92) qpIshg_pur‘ueweezgy SASUNIT 
op‘soezts 3TunASatn# T° Saou 

Te‘¢ee [T° eaou 

( r3deofaep:ge ‘xrqdqtun:¢ge ) ‘ 


ze/yp-zp/+(ds)  — T__ureaou 


ee ee 


2 atugqebundxg 


4 


23Funee2z7 
‘ 


:pug 3FunztUL 


SSWiLaAd 
T* eaour 


T°Tst 


<,4O 23FUAITUI/Sy .>‘O€ 


eTqeq afun jes : (T°op‘9e) sqtuq pu’ece 


zejutod LINN ezoqsez ?/ 


oP ‘c# 

xequnu 3tTun / op ‘zp 
o5 o3 Apeez se sn yreEW 
_ €e‘+(ds) T° eaour 
(9e)q7Isks pur’ yxseLPPY SASUNIT 


WSeedlAop AOpUles 





Example Device 565 


<,Z1%$ -- OTwros70d/s8%,>'9ST  SOSWLOd 
Pzom ezzque 20D/ (ds)z‘(Te)GNYWNNOD OI A eacu 
(ds)-_  T°2zT9 


OST-THAAT OANI FAT 
( ge:zqdaep ‘ge:xzadqtun ‘Te:qot ) / :orlmrosz0g 


“qsenbey 0/I e143 

uo euop ueeq Apeerzte sey Butyoeyo spunog ‘ 3senbex of ey sey Te 
-(sXempte se) zequtod eotaep eyA sey 9e “AT ut zequTod ytun eqQ eaeyq 
Apeezte 03 ¢€e sqoedxe AL 


(eTRNpeyos s,szeETTeO eyQA wo snqy) oruTSeg worz ATQOexTp xo ‘yseQ eqQ 
wory PEeTTes eq jyHfu Ar “yAsenbez of ue seyojedstp Atrtengoe orwrosi0eg 


Be ee en 


pug orutheqg = s"ezq 
(Te) Yowsa OL 'CHOON WUAOT# gq" eacu 
IPUDON OLUTbeg 


sqz 
— €2/08/TP ‘+ (ds) T“weaou 
<,pug orutbed/s%,>‘00Z oOSsNLNd 
:pug orutbeg 


ormz0jzeq = 8 "a8q 
oe FIEYNa 
:eqQeTpeumy orutbeg 


sseoo0rzd HutTTeo eqA Fo eTNpeyos ey uO At od 


Butjetduos ezozeq rSeTTeD 03 umNnjeZ 

pra orutbeg 
Te=ebessom ‘oe= 7204! (9e) q718%s par‘ Bewand SXSUNIT 
oe’ge T'escw 


Oana 
ds‘s¢ 1'bppe 
<,xTg=obessey x[T%=370g :S5swand/s%,>‘0Sz OSNLAd 
(dg)-‘¢e T°eaou 
(ds)-‘Te T° eacu 
OSZ-THAZT OANI aDaI 


= _— O08 TENA 
ATyOTNb styqQ e,eTdwoo LON PTP OM! (Te) SOWIa OI ‘NOINO GOLF zT2q 
(€®) SOWLd LINO ‘MSWINI @LINo# qesq 
:bsyenend orutbea 
Betz yo rnb eyqA reeTD “uot AueQWQe yseQ 
Sutpeeu se sn yreuw ‘eoTAep eyy enenb of peeu om 


"yseq 4803 03 seutT ---->! oe TpoumT - orutbeq 
e@seq3 3no QueuMOD ---->!/ (€®) SOWL LINA’SAILOW @LINo# 


*zxeeTo eq 

qou Aew ATetT3qns sty ‘Toy peATeEm eq OF speeu zSeseT AeYR WeT 
wory setdoo eotaep sty3 eDuTS “3Tq ATH, eyA S5uya3es Aq 

YO SF AT peqeotpuy sey zesn eyQ vey st uotyadeoxe ATuo ey 

i ()oruybeq ut etnpeyos s,zesn eq uo ()3TeM TSOAON ::: :UTZENINTE 


“uotqezedo ey3 xz0z pesn ATTensn st sseoo0id 


HuyTTeo eyQ ‘eaTQ0e ere seUTT CYR WEYM “ANOYITOM 20930eq eB 
8305 ysej eqQ ‘3no pequeumoo ,/, Ee MOTeq seUTT e423 ueqM 


WiSeadlAep Aopuled 


ezempzey pezeys q3tmM ------/ 
xzom ATQeTTez 03 EeDTASp e FOZ [eTQUesse BF ANq ‘xXSTP 
wez © rox pepeeu ATTeexr Wou st uoTAerATQze Fo edAW stays ------ 
‘yseq eq dn ortz OsTAZ ‘“ETNpeyqos zoesn 
ey3 UO pueUMOD eY4A Op ‘jou st eoTAep ey4QA FI *Asnq 
ST SDTASp 944 FF COS “pueUMOD EReTpouMT ue AOU st STUL 


Ssyenend olutbeq 
(ce) SOWLd LINA’aaddoLs aodn# 
‘Bsu ayqQ onenb ‘os JI ‘“GaddOLS ST 3FuUN ey FT Sos 


Sswenend orctbeg s°ouq 
TP ‘op asaq 
TP ’GaWNIUaAaN# A" sac 
qeya zeQQ3eEu OCU spUeUMOD GANNIUZASN TTe enenb 
‘sqdnzzequt Sutsn st / LdAwaLNI dal 


e3eTpeuml orutbeg euq 
TR‘op 1°3839q 
*ezey pepeeu yjnq ‘zgnqs Aqseu ‘yor -->/ oe atawsid 
TP ‘SaLWIGaWWI# T°" oe 
3eyA z0Q3eu OCU spueUMOD ejeTpeuMT TTe sseD0rd 


(peubtsun - syq=ooq) “37 oefez ‘ou: Papon orutbeg 
83tq 9T TTe ezedunop: OP ‘ANZ AZGAN# 
peqjoefexz eze sjsenbez edA3 xxx GLa ezns exe 3 yooyD eHuexz e oq! 


op’ (Te) aNWHHOD_OI m* eacu 
aata Aetd 03 3yun jeqm <- burdeexxooq: _€e/ (Te) LINA OL T*eacu 
4Z0M 02 peoquezend st ()OIATEM OS! (TE) AdAL NI’SOVSSAW LN# q*eacu 


(ds)-‘ee/oe/Tp TT weaocu 


Oana 
ds‘y# t 'bppe 
<,X1%$ -- orutbeq/s¢,>’€  OSWLAd 
PI0M exTQUe 3eD/ (ds)z‘(Te)GNYWNOD OI A eacu 
(ds)-_ —T"2T 
€-THART OANI 3941 
ana 
aa zemod ey3 xUTTa! Tooesas‘T# a byoq 


T-'THAaT OANI FSAI 
( ge:entaep ‘Te :qot ) : sorutbeg 


*zesn ey 03 buturnjexr ezoseq FOWSSEW IN 03 edXQ epou eyQ Wes 09 
ZOATIP eDTASpP eu3 30 AqtTtqtsuodsex ema 8,31 ‘“peystuts st ysenbexz 
ey} soumsse 3} ‘OSWATEU IN OF 308 ZI “3TEM TTT pue Hutpued T1T38 
_ST qsenbez ey seumsse 4F ‘GOWSSIN IN 03 208 JI ‘Betz & se 
(3dXL NI) OdkQ opou qseonbeyoI ey sesn uopjounz ()OIITEM exe EYL 

i INVLYOdNI 


*XeT Qe; peut 
peuzoszzed oq ued oseyy ‘Hbutpeezy3 eTbuts peeu jou op sysenbexz or euos 


*Buyssevoazad zejeT{T xox penenb st qsonbex 

eq ‘peutejqo eq jou ued sseDDe ejeTpeumy FI “YO st poyjeu Auy jSutsn 
exzozeq eotaep xzn0oX zoz ySnoue pooh st sty erns eG “ATO BATLOW GALINA 
eq3 sesn eTdurexe sty, ‘“Sutpeezyq3 ey3 op o3 sXem Aueu exe ozeyL 


“OTuzos19g 
eta peyouedstp st pueumoo ey ‘euop ueeq sey sty esouQ ~“weTqord e 


WS sdlAep Aopuled 





566 ROM Kernel Reference Manual: Devices 


ds‘y# T° bppe 
ds‘g# t°bppe 
<,XT%$ SAP PTS YSFFO PTS UST IMPU/s%,>'007 OSWLAd 
(ds)-‘(T®)HLONZT_OI T"eaou 
(ds)-’(T®)Lasado_oI T° eaou 
(ds)-’ (Te) vavd OL [*eacw 
00Z-TAAST O4NI 3531 


*YserD 03 TEATIP eDTAeP eYQ EsNeD TEAS UeD syndutT 
peq Jo uopyeuTquon ou 3eY3 Os poubtsep st eoTaep sTUL 


x ezq 
(Te) Twabow OL T°4TO 


ba 


ee en on ie 


‘euop sem YIOM ou 
aeq3 uanjex ATquezzn> Keyl, ‘peppe eze spueumod soy nok moys 03 
asn{ pepyaozd eze 3ey4Q3 spueumoD oTyTOeds eDTAep omy OTe Teg pue CO” 


= ormre, s‘ezq 
syoery JO requmN: (Te) TWOLOW OL ‘HOWULUAdSALAG/AZISNWU# T~ SAcu 
i sYDeTLUMNACSD 


ormzey, s°erq 
(Te) TwaLOW OL‘op 1" eAacu 
op’s €sArua# beaow 


eatzP (UMIK6) .G°E SATT AOOT 3F SyREu! :edXLeat703°D 


OorwmizeL s°erq 

(Te) TwaLoY OL T°ATO 
peqoejozdun seqeotput ozez/ rengeqsqorg 
peqzesut yAstTp seqeotTpuy ozez/ seqeqsebueyo 
(9= Qunosefueyo) ozez uinjexy: zsumyebueyqd 
Butyqqou od: 12030K, 
butyjou 1yees 
Butyjou :eaouey AQ 
bSutqqou :gurebueyqouey 
butyjou :qurebueyoppy 
(op 03 eTqeuoseez Sutyj0ou) Bbuyyqjou :qeseytn 
:2eBeTD 
:eqepda 


-Ktdde jou op spueumoo eseyQ ‘szezynq TeureqUyT ou sey 
SoTASP STYR SoUTS “sTEFFNQ TeUTSEQUT TTS seAepPTTeauy TeETO 


“w%O, uazngez AtTdurs om ‘ysTpueT e Uy OT AeEUOANe st stTYyR eoUTS ‘“euop ATTeRI0R 
ST STU T}3UN wmnqez jou seop pue ‘jods HuyyAsexr TeuzzF SAF OF YMO OT 
Tie seor0z ejepdg ‘spuewmmon butresznq Teurequy ere reeTD pue ejepdpn 


Oe ee ek ee ek 


_ormzeL s°eiq 
(Te) wouUT OL’GHOON WAAOI# 4" ecu 
:pTTeauL 
PORTIMMEY 


(GI'TWANT) peqioddns 30n TT / 
i [peeymMey 


(GQITWANI) poegroddns 30Nn OT 
Br 


»PeTTeZ yeenbex ()OI3zTOGy,, uznjez/ OP'GNOON WaFOI# beaow 
( ge:eDtaep ‘Te :qot ) ¢ O13t0qy 


WSe"eolAep Aopulel 


‘ 


*Tewmzou se ‘()Ssyktdeyw qata pettdez eq ysnu ebesseu ous: 

*(eqeTduon st qsenbeyor eq ‘OSWATdTY LN=adAL NI tO yOTNb sy! 

qsenbeyor ue st) sueddey Butyjou ‘ejeTduoo Apeezte sem qsenbeyor e439 ZI: 
*qgsenbeyor ue so butsseoozd ,dn Azzny,, 02 Lsandaa & st ()Or3TOGY: 


jasenbeyor ey3 yonoz 3,u0p os ‘butyzhue orazoqy 3,ue5 eM: 


pepusderd AW, © SCARY sUOT_ONIASUT 00089 WITH AOTTFUoD yeyQ spueuM0D 


eoTaep eyQ3 073 zeQjuTod e -- 9e 
atun ey 03 zequTod e -- ¢e 
yeoTq ysenbez of eyQA OF TeQuTOd e -- Te 
[4QTM peTTes eze suoT{AoUNZ [Te 
SpueUMIOD SsoTAep eYyQ AUSUETdUT QeYQ suoTROUNZ eYQ sutbeq ezreR 


Card 


RRR BEREAN MMR ER MERE ARE 


s3 
:pug orwze, 


(OSHATaTa LN OF TAAL NT_0yR sq0es HsyXtdoy) ‘ 
ebessou-Te! (ge) qtisks pu ‘Sswktdey sxASYNIT 
pug ormre,  s'euq 
(Te) sOWId OL’MOINS aor# as3q 
‘zesn eyQ 09 uzngqez asnf -- Hsu : 
Kidez 03 pesu 3,u0p eM ueYyy 3es TITIS BT 3TQ YOTN eyy ZT 
reqAeTpeumy orwze, 


(€®) SOWId LINA’SAILOW @LINoa# zT9q 
op 03 ¥TOM ezOM eARY JOU soOp yseQ eYyQ ------- 


“HATLOW ZeETO 3,U0p ‘yxseQ WoOITZ oueD sem OI! _ eReTpeuMT_OIWZTE], s*‘ouq 
(€®) SOWId LINO ‘ISWINI - GLINA#F 483q 


“3FO ATQ EaTROe SYA UrNQ O39 peeu Aew om ------! 


eAeTpewmy COWIE], s°ouq 
TP ‘oP 383q 
TP ‘S3LVIGSWNI# *eAouw 


“°"ZgZNAs YSeQ Op 2,UOp ‘eReTpeumIT sem OT: 


oP’ (TE) GNWAHOD OI 4° eaocu 
<,OIWIEL/s%,>‘O9T OSWLOAd 
( ge:zqdaep ‘ge:zqdatun ‘Te:qot ) / sOlwzeL 


“seq reazes SYA Wors peqTegs sem ysenbez 
eqa JT TO ysenbex eAeTpeumT ue seM STYR FT SATQOSUT se EDdTASP SYR 
yreU OF JOU smMoUy GI “Tesn eYR O23 yOeq ysenbez oF eyR spues OTWIe]L 


ge:qadaep ¢ee:qtun Te:qot: (oe) dul 


oe‘(m"op’oe)0 T"eAcu 

oe! (od) eTqejpu> =: T"BeT 

qeszzo eTqez 3eb 03 y Aq Atdtatow : op/z7# = A TST 
e3Mq mot ze ATuo yooT! op’ (Te) T+ANWNNOD OI q°eAcu 

zeyZ Of TOIZTe ON : (Tw) wowda or‘op q*eaou 

op‘o# beaouw 


Oana 
ds‘y# t’bppe 


wise adlNep Aopwel 





Example Device 567 


(Te) Youur OL ‘aaiiogy wagor#  q"eacu 
Te‘op T° eaocu 


pug ysntg s*beq 
op 17383 


qaod s,xse3 worzz sebessou Tee3s! Bswie5 = SASTIWO 
oe ‘ee T°" eaou 
:dooy ysntg 


= = zp ous 
(€®)SOWwId LINA’agddOLs anqN# 3esq 


9e‘(9e)qpIss pu T"eAcu 


(ds)-‘9e/Te/zP TT" wesou 
<,PeTTe :ysnTa/ss,>‘O0€  OSWiNd 
qsnTaz 


(-**dteyq qyStu ezoydeues y) “yYsnTJ e& JO STPpTu eyy ut ATeQAs e seop 
euceuos z+ ATQexestu sTTeF OSTe YI “YSNTF ut ATavWSIa 02 Sutpeeu 
wozz sn sdesy sTyL “ZERET AT erOQRSeZ ueYyQ pue ATq eYyQ FO 

@7eAsS PTO eYA eAeS ETOFOTEYNA OM “QUeITQUeeX Huyeq jou se peuTyep 
st doqg ‘ezey ut 3Tq GgddOLS S42 43TH wo seoh oTheu Auunz ouos 


-Aq dtts sqsenbez of euos 3eT AOU Op eM AeqQ 
oste pue ‘ssezbord ut yr0m AozAsep 02 Jou [nzerTed eq AsnuU eM 
-yoeq wey spues pue enenb eyy szo sqsenbez O/I TTe stind ysntz 


BR ee en ee ee en ee 


sz 
_ Te’+(ds) T° eaou 
€e Jou ge-oozew:qaxra:: (9e)q¢1sXs pu’Teuhts SXASINIT 
Teubts of yxseRz-CDTEW: CaXTd: : Te’ (€e)AsWLOIS aN T‘eacu 
yseu Teubts pezedezd! op ‘te qesq 
op xawalo 
TP’ (€e)LIGSIS aw q*eacu 
BHuyaow AF ATeQs OF ASEQ SYR _AOTH 
(€®)SOWLd LINA‘aaddoLs sNan# 
uo yoeq Hbutssen0zad uzn4 
(ds)-‘Te T°eaocu 
24zeqsTeuzequr 
[e>yaep=9y 3TUN=EV] ‘ 


ormze, e2zq 

qrzejgsTeuzre jury s°a8q 

<,PeTTeO :37e9S/8%,>‘0€  OSWLAd 
:qzeqs 


= _OrTmzeL eiq 
(€®)sowld LINA’daddOLs andW#  268q 
<,peTTes :dojshw/se.>‘0€  OSWLOd 

:doasin 

xstpuez e z0oz AT{ts reyAez st doqs! 


-Buysseooid 

qreqsez 03 32e4S eUO sexeq ATuo Ay ‘pensst ueeq esey 
sdoqs Aueu moy zej jeu ou *6b'e :eTqeyoeqs LON st puemI0D 
dojs eyZ ‘peatesez sft pueumo> Aze4Ss e& TT3UN pesseDoid 
buteq worz sqsenbex of erzngnz TTe dos pueummos doyjs eyqy 


ener ars 


WISb"ad|Aep ASPUeL 


pus 32mMPpu ss" eq 
(Ze)TwaLOwW OI = T°2T? _ 
= = :pug or 
(Ze) aowda OL ‘HLONATGVE WaaOL# q°eacu 
<,qqbueT peq,>‘OT SsWiod _ 
izmzqueT OL 


peaow eqep ou ‘Atteparur! 


ang: ormzey ezq 
e€e/ze’+(ds) T*weaouw 
tTe’‘ze T°eaocu 

spue 3IMPu 


qsez Azea sy yo Tnoueyidoo: 
®ZTs=0d 3SOP=Ty eDINoOs=oy! (9e)qTIsAs pu’ yoTNouEWAdOD SASUNIT 
yoo TgeyLtAdoo 
Asep 9 enrnos dems ‘jeuz0g pue eAtxmM r0gq / ty ‘ow xz 
_xpotaeynkdop = s "B 
uoT_oeITp uo epfoed / (Ze) T+ANYWWOD OL‘dwau aNo#  q°dup 


4 


yqbuet=0d- 

zezynq resn=Ty: 
xeputT yAstpuer=ow: 
’ 


Te’ (ze)vava Or T° escu 
pus_3IMpu s°beq 

(ze) Twnzov oI/op T*escw 
op‘(Z®)HLONAT_OI T*eaocu 
oe’ (Ze) LasaziQ OI T°ppe 
oe’ (ee) Wwd pu TT eeT 


xezgznq e7ep o3 3uUTOa 
O/I yqhuet ozez qaTM Teep--- 
seqtq [Te peaocu e4,0M eQeoTpUL 


eseq wer 03 3e8F5FO PPY 
O/I 203 ,, 203008, WSICNWA OF 3UTOd 


ae Dang 

Buypeesord ezoyeq ydnzzejuT roxy 3TeEM (9e)qtIshg pur‘atem SASUNIT 
ZOZ ATeM OF sTeUbTs 30D op‘ (ee) xseMSts npu T*escu 

LaOWaINI dal 


*qsenbez ptTea e eq ysnu At ‘rez sty uwe3306 ea,oM 


-""peq: zzqgueT Or s°euq 

eXzepunog z03D0es8 ueag! op ‘T-woLogs# T’pue 
(exeduop peuftsun) **-peq: IzqueytT or 
TeIOQ ETQegdedde yseybty st e7hq yseT: op ‘azIswwu# 
(9803 Queqzodut) °° ‘moTyzea0!: zzygueT_Ol 
yeszzo 03 yQbueT ppy! op’ (Z®) HLONAT OT 

[3esz30=0] ‘ 

ebuez stp uFqgtsM OL r0F Yooyo 


[3esz330=0a] ¢ 

“*speq: Izqueyt or s°euq 

équeuubtTe zo Azepunog 2z030e8 peg! TP ’T-woLogs# TT pue 
Tp/op T esow 

op‘ (ze) Lasaao OL T° eacu 


(3e8330=04a] - 

“sspeq/ xzqgueT OI s"euq 

dado st zequtod #,zesn x7 yxooyD?: (ze) €+vawa O©‘o# 4°383q 
Katrebet xzoz uofqezedo yoyo 


ee’ (ze) GINA OI T"eacu 
ze‘Te T° eacu 
(ds) -’ge/ze [T"weaow 


zequfod yfun 3e5/ 
qot Adop? 


Oana 


wise adlAep Aopwies 





Devices 


568 ROM Kernel Reference Manual 


qsenbez sty 3 op 


gebessou ou / yooTun xseL 
op 1°383 
<,68w309/8%,>'T SSWLOd 
Ssw7eD SASTIVO 
oe’ee T° esocu 
sebessopnjxen ; 4SeL 
qsenbez jxeu eyqQ 306 


(gpueumo0s ejeTpeumtT) esn ut eoTASep ¢ doortaten | ysez 
(ee) Sowa LINA‘SATLOW GLINa# 
eDzaep ey ACT 
sefessou ezouby ‘peddojs st eotaep / dooquTen : yseL 
(ee) sowta . LINO ‘qaddous ; @oane 
peddoqs eze em Jt ees ------ 
<,dnexyem++/8%,>'SL OSWIAd 
tezeRAzZeAS ASeL 
Oana 
agat xemod ey3 yuUTTa! Tooesags’T# g°54y0q 
$-THAaT OANI 354I 
aTeM SASTIVO 
oP’‘LP T"eAocu 
<,deetst++/s%,>'SL  OSWiOd 
rdooquten yseL 


efesseu meu e Toy yyemM :dooT utew 
(€®) SOwld GINA’ ((MSWENI ALINQiZAILOW ALINA)~) 333$# = 9" pue 
:ypoTuq AseL 
*qno seatesino yoeq ‘sebesseu ezrouw ou 7 


ebessou © 306 03 yorq doot 

ebessou eyQ youedstp 

doot pue eotaep yooTun ‘ebesseu ou zr ‘ebessou e 305 

eoTaep SY YOT 

ebessou e TOF ATeM 
(unz 03 
eoueyo e sjeh yse3 xno quoaaa peqsod eq Atqeqozd [Ttm ebesseu Asztz Sys) 
-Kxque uo epop Ssuje6 eq3 oj dumf om (37UNATUI UT) STTqM & TOF AYONSI Wa 
pexzeu yzod ey pey om esneveq “sty exTT se0b AI “TeATIp ey FO 
doot uyeu ey3 4TeQs WED MOU OM “TOTIEZTIETITUT YITM SuOp ere om ‘SPTX ‘HO 


ezepazeas YseL x erq 


oaNng 
ds‘ysy# T"ppe 
<,XTS=4SPL XTZ=OOTAST XTZ=3FUN ‘PTs=Teubts/sy,>‘ov OSWLAd 
(ds)-‘op T°eacu 
(ds)-‘ge T*eacu 
(ds)-‘ge T°esou 
(ds)-‘(9®)PTTg T° eacur 
OP-TEART OANI 25aT 


LP ‘oP esq 

La zeeTD: LP ‘O# 

Lp uy eaes pue ‘yseur eB oqUuy zequna ata eq ebueyo 
w8AFT, 3zod ebessouw exen! (€&)SOWIA dW’ TYNDIS wat qr eacu 
(€®) LIGDIs aN‘op q°eacu 
TeubysooTTy SASTIWO 

Tre qe Teubts Aue st T- : op ‘T-# 

Teubts e e7eccTTY 


q° 308q 
T*‘eaow 


sqdnizequy etqeug / (O08) ZTALOLNI ‘a TEVNALNI# 
sseippe eseq pxreog 3e5 / oe’ (ge) eseg pu 


WSB's0I|AONp"'ASPweI 


TOATESATIPPY SASTIWO 
OP’Siuod @LNI# beaou 
Te’(ee)st np [eet 
(ewasenSts npu’ip T"eacu 
Lp’ oP esq 
yseu Teubts zequmu ATq ATeAUCD / LP‘0# beaou 
ernqonz4s 4TUun uF eves / (ew) atabts npu’op q‘eaou 
Teuhfsooltw SsASTIVO 
Tre 3e Teubts Aue st T- / op ‘t-# beaow 
sqdnzzequy ,eqeTduop 0/1, xox Teubts e eAed0TTY ------ é 
LdOWaLNT 


TOATCS SYR TTEQSUT MON 

€ 3¥q Qduzzequy eTqz0g 

earnqoniz3s Adnzz9e jut of AUTO” 
erny7onazaAs ATUN ut eARS / 


eznqoNnzyAs eDTASp 03 AUTOd / ge’ (Ee) eDTAeC NpU 
zxequtod atuq / ee‘ (ds) p 
quezed ano wozz umop pessed queunbze ey Q qerp 


9e ‘aswaoaxasay 
<,utheg 4seL/s% .>'Se 


rupbeq AseL 


queudes qxeu 03 requTod ° Toa 


:astTbes corzdAu 


(zequtod queuhes eyQ worzy yorq se 7iq 
» ST STU) OP TI}4 zequmu Aue -- yRSueT queubes 9T Toa 
uBbtTe prom Huot ¥‘O douo 


SseIppe eTQeANoexe ASITF SYA ST ASTI Queuhes eyR TEAze uoTFIONITASsUT YxoU SUL 
“sTq43 YNoqe ezOUI MOTY O72 peou 

KrtTeex nok zt eouezezexr TeoTUYDe3 sod eT} EYR eeg ‘ezeY ASTT Queues 

e ayez> puey eM “ASTI Quewhes e zeqyZe sseIppe ETqeQNDexe YAszty SUR 

qe peqzejs st ssevord y ‘(sn jou) sessenorg roy [nyesn ‘oTheu sop euos 


yxseu {Tem 

zeqjutod (ssecsozd LON) Asey 
zequtod estaep 

zequtod qttsis 

zequtod 3tun 


ebesg zeqsthey 


*enuo qe noA TTeo 3yhtu yeyQ suexbord 

HuTASeaTATNu CYA TTS WITM erempzey pezeys FO uot zerATqQre xn0k 
Yate ezED eYeL “seoTAep ezempzey ,Teez, OZ Tnyesn Area st 
aqnq ‘xstp wer e zoz eTqetTsT3snf Area jou st sTyL ‘“SWTZ reReT e 
qe pessesozd eq Kew sqsenbez penenb 3ey3 os peptaoid st y4seL ¥ 


seutzNor peyzeTez yseQ eqQ sutbeq ez0eH 


Se ee 


ee 


Ce ee en rarer 


MM EE EB EE EE ARE EE RIE EE EOE IE I OE OR IE EB AE IE OE MEE EO OE OB HE OE BE 


oruzeL 
qqzeqsTeuzequI 4 = 1sq 


$T  s*beq 
op = 9°383 


9e/te/zp'+(ds)  T"weaow 
op ’zp T* Saou 


ipug UsnTZ 


dooT ysnta s"e2q 


Ssypitdew SxSTTWO 


WSB"sdIAOp AOPWIBI 





Example Device 569 


‘epoopug 


*(qunyq epoo eThuts e Ajtuo sey wezbozd sTYyq) ese 

SBTYR UT EFesS ST QT QeYR MOUH IT pue ‘op og butya .3yhbTr,, ey3 eq OF sueddey 
AT esneseq ezey 3t and r ‘ezes sXemte oze nok Kem jeyQ -- 5eq wor syQ 
zeqze 3yHtzr 3Tt and 03 yo st ar {He wor eyQR ezoseq jou st pue ‘syuny ueds 
qou seop jt ezns eyeW ‘spoo aznoX Fo pue eyA sMoys QeYQ TeYTeEU e ST epoopua | 


ang 
0 M°Od 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 
SNOTLINI 


qzeqs 03 szezznq sodebtuy # / tT’ szezznqumu_ :_upur 
zeputTA zeddn : T- (HOWHLNRaSaLAG/AZISWWE) Tkozeddn upur 
io < LSaN ‘sxXD0TQ peazesez T! sxT@ser_upu 
(eTqeuoseez eq Asmu) yOeTZ/soes / UTASUOLOES ‘AOeTLATGA_apu 
uTu = 3enu ‘yD0Tq TeoTboT/soes / T‘xATdzegqsoes_ upu 
npeey, euo AtTuo sey yxstp Wwa / T‘speeyumu_upu 
yxOoTq eB ut spzombuot # / ¥/AOLOES ‘APOTHOZ TS _upu 
eueu ut ,Wa, ez0QS : O000PYZs$ ‘eueNP_uUpu 
*aue soaebtuy ut spzom Buot # ? ZT ‘eztsetqez upu 
eweu TeATIp FO ssexrppy - euentu‘euenoexe upu 
eponsodexen roy yexoed ezTTeTATFUI ------ tos 
iQyUl upu 

ZNNOWOLNY GNAT 


0 M*od 
OaNg 


eure Aur ‘GWYN NI+ST nput SONOTLINI 


Wise edlAep Aopwel 


zppe eutqnoz ydnazequr / xzqutAur’gqaoo_sI+st_npu SNOTLINI 
y Aqtzotad qur / v‘Iud NI+sf npu ALAGLINI 
LaNwaLNI dar 
s’ Idd_NI+qo3_npu ALAGLINI 
MSWL LN‘Sd4L_N1+qo3_npur ALAGLINI 
euendu GWYN NI+q3 npu SNOTLINI 
: ouenAw ‘SWYN_N'T ONOTLINI 
‘ Taodssw IN‘ WdkL_NT ALAGLINI 
qzod ebessow e yQTM sqzeqs aTun! ZYONSI wa’sowld dN ALAGLINI 
eoTAep SYR SZTTETITUL ------ : 
:3y7Ur npur 


MR MMR BM RH MR EE EE ME OE IEEE ME EE EH RE BE MR RE 


releivicg 
sqa afxeAu 
: 


SpoDd UOoTATpUOD orez Aes op ’o# beaou uruxe Au 


ufeyo ydnzzequt ey ut 
zeazes 3xeu eyQ AzQ TTT zeTpuey Adnzzequt ey os 
@poD uoTATpuOD orez eyQ sjes AUTOd 4Txe sTYyR 


ayxe mou qtxefxu s"eiq 
Herz ozez zee{o op‘T#  beaou 


*zeazes Adnzz0equtT 
qxeu eyQ TTeS 4,Use0p reTpuey adnazzequT ey 
ReYQ OS BpoDd UOTRTPUOD orez eYQ TeeTO MoU 


Pe Re ee 


Teubts sSxksTTVO 

ueqsks oj zequtod je5 / ge’ (oe) arisds 1 pu T[* Saou 
Te’ (Te)qoq_npur = T"eeT 

op‘ (Te) xsenSts_npu T"eaocu 

zequtod estaep yey / oe’ (Te) extAeq Npu T*esouw 


pezanoso sey ydnzzequy ue 3eYyR yseQ eyQ Teubts ------ 


ATqQ zauTt s,reTToOrQUOD eTbbo3 / (08) WOWLNI ‘O# q* encour * 

eutu jou ‘QTxe ‘Qes jou ZF / wuxeAu s*beq * 
butqdnzzequy w,I JF ees‘ (O&) TTELOLNI‘SNITINdNWI# 4° 3830 * 
sseippe oseq preog o3 AutTod / oe’ (98) eseq pur [T° eaou * 
:zqutAu 


(wivd Sx) jAzque uodn ezngqonzqs ytun ey3 03 bufqutod eq ptnoys Ty: 


LdnwaLNiI aat 


*sZeATIp eDTASp , Tau, ‘zeyQo ut ATTnzsseoons 

pesn ueeq sey epod XeTWTIS ‘“TeATIp styR rox ezempzey Aue AT Teer 

3,UsSt eeYQ SDUTS suotqezedo uye_reD ATWO To exXeZ Asenu pue ‘peTqestp 
Krpewuzou st epoo sty, °*(3t Op TTT pzeoqkex ey wo NuNIgTY Suyssezd) 
qsenbez yoeo sseoord TItM 3T ezozeq qdnzzequt omQ TeaeT e& TOF ATeM 

03 S2FASp eYR SSNES TTTM epood sty ‘peTqeue st LINWMAINI GaI S43 FI “yo 
pequeumros squeucduios TeTonrD euos YyQTM ‘TeTpuey ydnzzequt Aummp e st ereH 


BR ee ee 


BR EEE EE MM RRR 


ebessenjxen 7sSeL s‘erq 


ge ut yoeq attsks 306 ge‘se bxe 
oruwresz08g azsq 
ge’se 5xe 


eoertd aqy6t2z ut 214d eotaep and 
Te’op T° saou 


WSe"edlNep ASpwied 





vices 


De 


570 ROM Kernel Reference Manual. 





appendix C 


FLOPPY BOOT PROCESS AND 
PHYSICAL LAYOUT 


The first two sectors on each floppy disk contain special boot information. These sectors are read 
into the system at an arbitrary position; therefore, the code must be position independent. The first 
three longwords come from the include file devices/bootblock.h. The type must be BBID_DOS; 
the checksum must be correct (an additive carry wraparound sum of Oxffffffff). Execution starts at 
location 12 of the first sector read in. 


The code is called with an open trackdisk.device I/O request pointer in Al (see the “Trackdisk” 
chapter for more information). The boot code is free to use the IO request as it wishes (the code 
may trash A1, but must not trash the I/O request itself). 


The boot code must retum values in two registers: DO and AO. DO is a failure code — if it is non-zero 
then a system alert will be called, and the system will reboot. 


If DO is zero then AO must contain the start address to jump to. The strap module will free the boot 
sector memory, free the boot picture memory, close the trackdisk.device I/O request, do any other 
cleanup that is required, then jump to the location pointed to by AO. 


Boot code may allocate memory, use trackdisk.device to load relocatable information into the 
memory, then retum with DO=0 and AO pointing to code. The system will clean up, then call the 
code. 


Floppy Boot Process and Physical Layout 571 


COMMODORE-AMIGA DISK FORMAT 
The following are details about how the bits on the Commodore-Amiga disk are actually written. 


Gross Data Organization: 


3.1/2 inch (90mm) disk 
double-sided 
80 cylinders/160 tracks 


Per-track Organization: 


Nulls written as a gap, then 11 or 22 sectors of data. 
No gaps written between sectors. 


Per-sector Organization: 


All data is MFM encoded. This is the pre-encoded contents 
of each sector: 


two bytes of 00 data (MFM = SAAAA each) 
two bytes of Al* ("standard sync byte" -- MFM 
encoded Al without a clock pulse) 
(MFM = $4489 each) 
one byte of format byte (Amiga 1.0 format = $FF) 
one byte of track number 
one byte of sector number 
one byte of sectors until end of write (NOTE 1) 
[above 4 bytes treated as one longword 
for purposes of MFM encoding] 
16 bytes of OS recovery info (NOTE 2) 
[treated as a block of 16 bytes for encoding] 
four bytes of header checksum 
[treated as a longword for encoding] 
four bytes of data-area checksum 
[treated as a longword for encoding] 
512 bytes of data 
[treated as a block of 512 bytes for encoding] 


NOTE: The track number and sector number are constant for each particular sector. 
However, the sector offset byte changes each time we rewrite the track. 


The Amiga does a full track read starting at a random position on the track and going for 
slightly more than a full track read to assure that all data gets into the buffer. The data 
buffer is examined to determine where the first sector of data begins as compared to the 
start of the buffer. The track data is block moved to the beginning of the buffer so as to 
align some sector with the first location in the buffer. 


Because we start reading at a random spot, the read data may be divided into three chunks: 
a Series of sectors, the track gap, and another series of sectors. The sector offset value tells 
the disk software how many more sectors remain before the gap. From this the software 
can figure out the buffer memory location of the last byte of legal data in the buffer. It can 
then search past the gap for the next sync byte and, having found it, can block move the 
rest of the disk data so that all 11 sectors of data are contiguous. 


Example: 
The first-ever write of the track from a buffer looks like this: 
<GAP> |sector0|sectorl|sector2|...... |sector10| 
sector offset values: 
11 10 Ge. Nesdlecdte 1 


(If I find this one at the start of my read buffer, then I know 
there are this many more sectors with no intervening gaps before 


572 Amiga ROM Kernel Reference Manual: Devices 


I hit a gap). Here is a sample read of this track: 
<junk>|sector9|sectorl0|<gap>|sector0|...|sector8|<junk> 
value of ‘sectors till end of write’: 

2 1 svete 11 wee 3 
result of track re-aligning: 
<GAP>|sector9|sectorl0|sector0|...|sector8| 
new sectors till end of write: 

11 10 9 sage 1 


so that when the track is rewritten, the sector offsets 
are adjusted to match the way the data was written. 


Sector Label Area This is operating system dependent data and relates tohow AmigaDOS 
assigns sectors to files. Reserved for future use. 


MFM TRACK ENCODING 


When data is MFM encoded, the encoding is performed on the basis of a data block-size. In the 
sector encoding described above, there are bytes individually encoded; three segments of 4 bytes 
of data each, treated as longwords; one segment of 16 bytes treated as a block; two segments of 
longwords for the header and data checksums; and the data area of 512 bytes treated as a block. 


When the data is encoded, the odd bits are encoded first, then the even bits of the block. 


The procedure is: Make a block of bytes formed from all odd bits of the block, encode as MFM. 
Make a block of bytes formed from all even bits of the block, encode as MFM. Even bits are shifted 
left one bit position before being encoded. 


The raw MFM data that must be presented to the disk controller will be twice as large as the 
unencoded data. The relationship is: 


1->01 
0->10 sif following a0 
0->00 ;if following a 1 


With clever manipulation, the blitter can be used to encode and decode the MFM. 


Floppy Boot Process and Physical Layout 573 


AbortIOO, 7 
Absolute_Joystick.c, 95 
Accessing a Device, 2 
ADCMD_ALLOCATE command, 22 
examples, 23 
ADCMD_FINISH command, 26 
ADCMD_FREE command, 24 
ADCMD_LOCK command, 24, 25 
ADCMD_PERVOL command, 26 
ADCMD_SETPREC command, 24 
ADCMD_WAITCYCLE command, 27 
AddTime(Q), 295 
ADIOF_NOWAIT flag, 23 
ADIOF_PERVOL flag, 25 
ADIOF_SYNCCYCLE flag, 26 
ADIOF_WRITEMESSAGE, 25 
Allocate_Misc.c, 340 
Alloc_Misc.a, 339 
Amiga BootStrap, 257 
boot mechanisms, 258 
bootblock booting, 259 
bootpoint booting, 259 
expansion board configuration, 257 
nodes, 258 
AMIGA keys, 79 
Amiga System Devices, 1 
accessing functions, 8 
asynchronous I/O requests, 5 
closing, 7 
commands, 4 
definition, 2 
device base address pointer, 8 
device names, 3 
device specific command prefixes, 4 
devices with functions, 8 
error checking, 6 
error indications, 6 
error processing, 6 
error reporting, 6 
Exec command prefixes, 4 
gracefully exiting, 7 
opening, 3 
passing I/O requests, 3 
synchronous I/O requests, 5 
ARPABET, 144 
Audio Channels, 13 
allocation key, 24 
allocation/arbitration commands, 22 
allocation, 21, 22 
changing the precedence, 24 
combinations, 22 
freeing, 24 
Lock, 22 


multi-channel, 24 
stealing, 21, 22 
Audio Device, 13 
AbortIOO, 18 
additional information, 34 
BeginIOOQ, 18 
changing the volume, 26 
channel, 14 
CloseDeviceQ, 18 
closing, 18 
CMD_FLUSH, 27 
CMD_READ, 27 
CMD_RESET, 27 
CMD_START, 27 
CMD_STOP, 27 
CMD_WRITE, 25 
commands and functions, 15 
definitions, 14 
device interface, 16 
double-buffering, 26 
free, 17 
hardware control commands, 25 
1ORequest block, 16 
TORequest structures, 16 
lock, 17 
opening, 16 
playing a sound, 25 
precedence of users, 22 
precedence, 17 
Teserve, 17 
sample, 14 
scope of commands, 17 
simple audio example, 18 
starting a sound, 27 
steal channel, 22 
stopping a sound, 26, 27 
Wait(, 18 
WaitPortQ, 18 
Audio Hardware, 22 
Audio.c, 19 
Audio_8SVX.c, 28 
BattClock Resource, 325 
additional information, 327 
functions, 325 
BattMem Resource, 327 
additional information, 327 
functions, 327 
BeginIOO, 4, 5, 18, 271 
Boot priority 
floppy disks, 258 
Caps Lock key, 78 
CauseQ), 314 
CBD_CHANGEHOOK command, 42 


Index 575 


caveats, 43 
CBD_CURRENTREADID command, 40 
Cbio.c, 50 
Changehook_Test.c, 47 
CheckIOO, 6 
CIA Resource, 328 

additional information, 335 

functions, 328 

reading and writing ICRs, 329 

reminders, 329 

timer allocation, 328 
Cia_Interval.c, 329 
Clipboard Device, 35 

additional information, 59 

advanced uses, 38 

closing, 42 

CMD_READ, 41 

CMD_UPDATE, 40 

CMD_WRITE, 39 

commands and functions, 36 

current clip, 40 

data, 37 

device interface, 37 

disk file, 37 

end-of-clip, 41 

IFF, 38 

TORequest structures, 37 

io_Offset, 39 

monitoring changes, 42 

multiple clips, 38 

multiple units, 38 

new features, 35 

opening, 37 

posting, 40 

post, 41 

reading, 41 

unit numbers, 38 

updating, 40 

writing, 39 
Clipboard Tool, 38 
Clipdemo.c, 43 
ClipID, 41 
Clip 

identification, 37 
Closing A Device, 7 

outstanding I/O requests, 7 
CMD_CLEAR Command, 310 
CMD_READ Command, 307 
CMD_UPDATE Command, 310 
CMD_WRITE command, 177 
CMD_WRITE Command, 308 
CmpTime(Q, 295 
Commodore SCSI Drives 


unit numbers, 250 
Complex_Serial.c, 280 
Console Device, 61 

additional information, 86 

caveats, 81 

character output, 66 

closing, 65 

console units, 63, 64 

control sequence introducer, 78 

control sequences, 67 

device interface, 63 

input event qualifiers, 78 

input stream, 75 

I/O request structures, 63 

keyboard input, 66 

new features, 61 

OpenDevice flags, 64 

raw events, 77 

raw input types, 77 

reads, 74 

system functions, 62 

window bounds, 75 
Console.c, 81 
Current Clip, 40 
Demo_Dump.c, 190 
Device Specific Commands, 2 
devices/audio.h, 16 
devices/clipboard.h, 37, 40 
devices/gameport.h, 92 
devices/hardblocks.h, 256 
devices/inputevent.h, 105, 106 
devices/narrator.h, 134 
devices/parallel.h, 161 
devices/printer.h, 175 
devices/prtbase.h, 181, 196 
devices/scsidisk.h, 251 
devices/serial.h, 267 
devices/timer.h, 287 
devices/trackdisk.h, 305 
Digital-To-Analog, 13 
Disk Resource, 335 

additional information, 337 

allocation, 336 

functions, 335 
DISKINSERTED message, 314 
DISKREMOVED message, 314 
DoIO0O, 4, 5 
DoSpecial(Q, 199 

parameters, 199 
E-Clock, 287 

E-Clock time, 298 

ECLOCK Timer Unit, 288 

EClock Val, 298 


576 Amiga ROM Kernel Reference Manual: Devices 


Ejecting a disk, 311 
End-of-Clip, 41 
End-of-File, 41 
EspsonX Driver, 210 
data.c, 214 
density.c, 230 
dospecial.c, 217 
init.asm, 213 
macros.i, 211 
makefile, 210 
printertag.asm, 212 
render.c, 221 
rev.i, 212 
transfer.asm, 225 
transfer.c, 228 
ETD_CLEAR Command, 310 
ETD_FORMAT Command, 311 
ETD_MOTOR Command, 310 
ETD_RAWREAD Command, 315 
ETD_RAWWRITE Command, 316 
ETD_READ Command, 307 
ETD_SEEK Command, 314 
ETD_UPDATE Command, 310 
ETD_WRITE Command, 308 
Exec Commands, 2, 4 
exec/errors.h, 6 
exec/interrupts.h, 106 
exec/io.h, 4 
Exec error codes, 187 
Filesystem Resource, 337 
additional information, 338 
Floppy Disk, 306 
floppy boot process, 571 
floppy disk format, 572 
floppy physical layout, 571 
MFM encoding, 573 
V/O, 306 
FlushDeviceQ, 342 
Flux Format, 315, 316 
FTYXT, 39 
Full_Narrator.c, 151 
Gameport Connectors, 104 
Gameport Device, 87 
additional information, 100 
closing, 90 
commands and functions, 88 
connectors, 87 
controllers, 89 
determining controller type, 94 
determining triggering conditions, 93 
IORequest structures, 89 
joystick controller, 90 
joystick controller, 93 


mouse controller, 90 

mouse controller, 92 

opening, 89 

reading, 91 

setting controller type, 94 

setting triggering conditions, 92 

triggering events, 92 

units, 104 

use protocol, 94 
Gameport Events, 91 
GamePortTrigger structure, 92 
GetSysTimeQ, 290 
Get_Disk_Unit_ID.c, 336 
Get_Filesys.c, 337 
Get_Systime.c, 290 
GPCT_ABSJOYSTICK flag, 90, 94 
GPCT_ALLOCATED flag, 90, 94 
GPCT_MOUSE flag, 90, 94 
GPCT_NOCONTROLLER flag, 90, 94, 95 
GPCT_RELJOYSTICK flag, 90, 94 
GPD_ASKCTYPE command, 94 
GPD_ASKTRIGGER command, 93 
GPD_READEVENT command, 91 
GPD_SETCTYPE command, 94 
GPD_SETTRIGGER command, 92 
GPTF_DOWNKEYS flag, 92 
GPTF_UPKEYS flag, 92 
Graphic Dumps 

additional notes, 194 
hardware/custom.h, 339 
Harmony, 13 
HDToolBox, 253 
HD_SCSICMD command, 251 
Hookface.asm, 56 
Hook, 42 
HP_LaserJet Driver, 231 

data.c, 235 

density.c, 242 

dospecial.c, 237 

hp_rev.i, 233 

init.asm, 233 

macros.i, 231 

printertag.asm, 232 

tender.c, 240 

transfer.asm, 243 

transfer.c, 242 
I/O request, 2 

creating, 2 
IDCMP, 114 
IECLASS_NEWPOINTERPOS, 106, 110 
IECLASS_POINTERPOS, 110 
iffparse.library, 35, 38, 353 
IFF 


Index 577 


chunk, 352 

color map chunk, 352 

definition, 351 

file contents, 351 

file extensibility, 354 

FORM and chunk registry, 429 

FORM, 352 

ILBM, 352 

introduction, 351 
Index Pulse, 317 
IND_ADDHANDLER Command, 108 
IND_REMHANDLER Command, 109 
IND_SETMPORT command, 107 
IND_SETMTRIG command, 107 
IND_SETPERIOD Command, 113 
IND_SETTHRESH Command, 112 
IND_WRITEEVENT Command, 109 
IND_WRITEEVENT command, 110 
Input Device, 101 

adding a handler, 108 

additional information, 118 

and Intuition, 114 

closing, 106 

commands and functions, 102 

designing an input handler, 108 

determining current qualifiers, 113 

device interface, 103 

event handler, 108 

generating input events, 109 

input events, 105 

key repeat events, 113 

memory deallocation, 109 

new features, 101 

opening, 103 

PeekQualifierQ), 113 

removing a handler, 109 

setting key repeat interval, 113 

setting key repeat timing, 112 

setting mouse port report, 107 

setting mouse port, 107 

setting the mouse position, 110 

time specification, 104 
Input Event Chain, 108 

multiple events, 108 

new events, 108 
Input Events 

generators of, 109 

Intuition handling of, 108 
Input Qualifiers, 114 
Input Request Block, 103 
InputHandler.a, 116 
International Phonetic Alphabet, 144 
Interrupt, 314 


578 Amiga ROM Kernel Reference Manual: Devices 


Intuition 
as input device handler, 108 
mouse input, 104 
IOAudio, 16 
IOB_QUICK flag, 271 
IOCIipReq, 37 
IOExtPar, 161 
IOExtSer, 267 
IOStdReq Structure, 63, 89, 249 
IOTDF_INDEXSYNC flag, 316 
IOTDF_WORDSYNC flag, 316 
io_ParFlags, 166 
io_PTermArray, 163, 165 
io_SerFlags, 276 
io_TermArray, 272 
Joystick Controller, 90, 93 
KBD_ADDRESETHANDLER command, 124 
KBD_READEVENT command, 128 
KBD_READMATRIX command, 121 
KBD_REMRESETHANDLER command, 124 
KBD_RESETHANDLERDONE command, 124 
Keyboard Device, 104, 119 
adding a reset handler routine, 124 
additional information, 130 
closing, 121 
commands and functions, 120 
device interface, 121 
TORequest structures, 121 
keyboard events, 119 
opening, 121 
reading keyboard events, 128 
reading the keyboard matrix, 121 
removing a reset handler routine, 124 
signaling the end of a reset routine, 124 
Keyboard_Events.c, 128 
KeyHandler.a, 127 
Key_Reset.c, 125 
Light Pen, 90 
macros.i, 210 
Makeup Of Speech, 144 
Message Port, 2 
creating, 2 
MFM encoding, 315, 316 
MICROHZ Timer Unit, 288 
Misc Resource, 280, 338 
additional information, 343 
allocation, 339 
functions, 339 
Mouse Button Events, 104 
Mouse Controller, 90, 92 
Mouse Movement Events, 104 
mouth_rb 
sync field values, 141 


Multiple Asynchronous I/O requests, 5 
Multiple_Timers.c, 293 
Narrator Device, 131 
additional information, 158 
closing, 136 
CMD_READ, 134 
CMD_WRITE, 134 
commands and functions, 132 
controlling speech characteristics, 136 
device interface, 133 
dialect, 136 
introduction, 134 
mouth movement IORequest, 133, 135 
mouth movements, 141 
new features, 131 
OpenDevice() flags, 135 
opening, 135 
phonemes, 143 
Punctuating phonetic strings, 144 
reading, 141 
speaking, 136 
speech IORequest, 133 
syllable synchronization, 141 
technical explanation, 149 
word synchronization, 141 
writing phonetically, 143 
writing, 136 
narrator_rb 
field descriptions, 136 
field descriptions, 137 
field descriptions, 138 
NDF_NEWIORB flag, 135, 138 
NDF_SYLSYNC flag, 138 
NDF_WORDSYNC flag, 138 
OpenDeviceQ, 3 
Opening A Device, 3 
OpenResource, 324 
Parallel Device, 159 
additional information, 168 
break conditions, 163 
closing, 162 
commands and functions, 160 
device interface, 161 
EOF mode, 163 
error codes, 167 
flags, 166 
io_PTermArray, 163, 165 
null-terminated write, 162 
opening, 161 
parameters, 165 
querying the device, 166 
reading, 162 
setting parameters, 165 


status bits, 166 
terminating a read or write, 163 
writing, 162 
Parallel.c, 167 
PARF_ACKMODE flag, 166 
PARF_EOFMODE flag, 163, 166 
PARF_FASTMODE flag, 166 
PARF_SHARED flag, 161, 166 
PARF_SLOWMODE flag, 166 
PBFB_NOMOUNT flag, 256 
PDCMD_QUERY command, 166 
PDCMD_SETPARAMS command, 165 
PeekQualifierQ, 113 
Pending Post, 41 
Phonemes, 143 
consonant groups, 145 
consonants, 143 
contraction and special symbols, 145 
contractions, 144 
digits and punctuation, 144 
diphthongs, 143, 145 
example text, 149 
glottal stop, 146 
hints for intelligibility, 148 
punctuation, 148 
sentence length, 148 
special symbols, 144 
stress and intonation, 146, 147 
Stress mark placement rules, 146 
vowel groups, 145 
vowels, 143 
POTGO Resource, 343 
Potgo Resource 
additional information, 345 
functions, 343 
PRD_DUMPRPORT command, 187 
PRD_PRTCOMMAND command, 178 
PRD_QUERY command, 186 
PRD_RAWWRITE command, 177 
Pre_V36_Device_Use.c, 9 
Printer Device, 171 
access, 173 
additional information, 246 
alphanumeric drivers, 198 
changing printer preferences, 182 
closing AmigaDOS printer device, 174 
closing, 177 
commands and functions, 172, 179 
CommandTable, 198 
creating drivers, 196 
data structures, 175 
device interface, 175 
direct use, 173 


Index 579 


double buffering, 204 
driver modules, 196 
dumping a RastPort, 187 
dumping buffer, 205 
error codes, 187 
Exec printer I/O, 175 
graphic driver modules, 196 
graphic preferences, 183 
graphics printer drivers, 203 
ISO color table, 181 
NULL-terminated writes, 177 
obtaining printer data, 181 
opening AmigaDOS printer device, 173 
opening, 175 
parallel status bits, 186 
Preferences, 198, 200 
print request guidelines, 177 
printer command definitions, 178 
printer special flags, 188 
printing with corrected aspect ratio, 189 
processes and tasks, 174 
querying the device, 185 
sending printer commands, 178 
serial status bits, 186 
strip printing, 193 
suggested typefaces, 181 
text preferences, 182 
timeout, 198 
two methods of output, 173 
using directly, 175 
writing processed text, 176 
writing unprocessed text, 176 
Printer Driver, 171, 196 
buffer deallocation, 206 
character conversion routine, 201 
CommandTable, 198 
DoSpecialQ, 199 
driver modules, 196 
example source code, 209 
extended character table, 200 
graphic driver modules, 196, 203 
printertag.asm, 208 
RenderQ, 203 
SetDensityQ, 208 
testing, 209 
Transfer, 206 
printerIO Union, 175 
printertag.asm, 196 
fields, 200 
parts, 197 
Printer_Data.c, 181 
PRT:, 173 
closing, 174 


opening, 173 
writing output, 173 
PStat 
printer device status structure, 186 
Query_Serial.c, 341 
Quick I/O, 4, 271 
RastPort, 187, 193 
building dimensions, 189 
dump arguments, 188 
printing a non-displayed, 189 
Read_BattClock.c, 326 
Read_Keyboard_Matrix.c, 122 
Read_Potinp.c, 343 
RenderQ), 203 
cases, 203 
clearing and initializing pixel buffer, 205 
closing down, 206 
dumping a pixel buffer, 205 
master initialization, 203 
pre-master initialization, 203 
putting pixels in a buffer, 205 
switching to next color, 206 
ReplyMsgQ, 292 
Reset Handlers, 124 
Resources, 323 
BattClock Resource, 325 
BattMem Resource, 327 
CIA resource, 328 
Disk resource, 335 
FileSystem resource, 337 
include files, 325 
interface, 324 
listing, 324 
Misc resource, 338 
OpenResource(Q), 324 
Potgo Resource, 343 
RigidDiskBlock, 253 
creation, 253 
non-ROM filing system, 257 
specification, 253 
use of information, 256 
Run Length Encoding, 205 
SatisfyMsg, 40 
SCSI Device, 247 
additional information, 263 
closing, 250 
commands and functions, 248 
device interface, 249 
opening, 249 
RigidDiskBlock, 253 
SCSI-direct, 250 
system functions, 248 
unit numbers, 249 


580 Amiga ROM Kernel Reference Manual: Devices 


SCSI-Direct, 250 
ModeSense setup, 251 
SCSICmd, 251 
SCSICmd, 251 
fields, 252 
SCSIF_AUTOSENSE flag, 252 
SCSL_Direct.c, 260 
SDCMD_BREAK, 279 
SDCMD_QUERY command, 278 
SDCMD_SETPARAMS command, 275 
Sending A Command To A Device, 4 
SendIOO, 4, 5, 270 
SERF_7WIRE flag, 267 
SERF_EOFMODE flag, 272 
SERF_QUEUEDBRK, 279 
SERF_SHARED flag, 267 
Serial Device, 265 
additional information, 284 
alternative I/O modes, 270 
break command, 279 
break conditions, 272 
buffered characters, 267 
closing, 268 
commands and functions, 266 
device characteristics, 265 
device interface, 266 
EOF mode, 272 
error codes, 279 
high speed operation, 271 
io_TermArray, 272 
multiple ports, 280 
NULL-terminated write, 268 
opening, 267 
parameters, 275 
querying the device, 278 
quick I/O, 271 
reading, 267 
separate tasks, 273 
serial flags, 276 
setting parameters, 275 
status bits, 278 
terminating the read, 272 
using BeginIOO, 271 
writing, 268 
SetDensityQ, 208 
Setting The Mouse Position 
basic method, 110 
pre-V36 absolute position, 110 
pre-V36 relative position, 110 
36 absolute position, 110 
36 normalized position, 110 
V36 relative position, 110 
Set_Mouse.c, 111 


Set_Prefs.c, 183 
Simple_Serial.c, 268 
Simple_Timer.c, 299 
Sound Synthesis, 13 
Speak_Narrator.c, 139 
SPECIAL_ASPECT flag, 189 
SPECIAL_NOPRINT flag, 194 
Speech Output 
introduction, 134 
Strip Printing, 193 
aspect-ratio-corrected image, 194 
height of strip, 194 
procedure, 194 
smoothing, 194 
Structures 
DriveGeometry, 309 
EClockVal, 287 
GamePortTrigger, 92 
GamePortTrigger, 107 
IEPointerPixel, 106 
TEPointerTablet, 106 
InputEvent, 91, 104, 106, 110 
Interrupt, 106 
IOAudio, 16 
IOClipRegq, 37 
IODRPRegq, 175 
IODRPReq, 187 
IOExtPar, 161 
IOExtSer, 267 
IOExtTD, 305 
IOExtTD, 305 
1OPrtCmdRegq, 175 
IOStdReq, 103, 175, 249 
mouth_rb, 133 
narrator_rb, 133 
PrinterData, 181 
PrinterData, 197 
PrinterExtendedData, 181 
printerIO, 175 
PrinterSegment, 196 
SatisfyMsg, 40 
SCSICmd, 251 
timerequest, 103, 112, 113, 287 
timeval, 287 
SubTimeQ, 295 
Swap_Buttons.c, 115 
Sync’ed Read and Write Limitations, 316 
System Time, 290 
Taking Over The Serial Hardware, 280 
TDF_ALLOW_NON_3_5 flag, 307 
TD_ADDCHANGEINT Command, 314 
TD_CHANGENUM Command, 313 
TD_CHANGESTATE Command, 312 


Index 581 


TD_FORMAT Command, 311 
TD_GETDRIVETYPE command, 312 
TD_GETGEOMETRY command, 309 
TD_GETGEOMETRY, 313 
TD_GETNUMTRACKS Command, 312 
TD_MOTOR Command, 310 
TD_PROTSTATUS Command, 312 
TD_RAWREAD Command, 315 
TD_RAWWRITE Command, 316 
TD_REMCHANGEINT Command, 314 
TD_SEEK Command, 314 
Terminate_Parallel.c, 163 
Terminate_Serial.c, 272 
Text To Speech 
introduction, 134 
Time Events, 104 
Timer Device, 104, 285 
adding a time request, 291 
additional information, 302 
closing, 290 
commands and functions, 286 
device interface, 287 
E-Clock time, 287, 298 
functions, 287 
multiple timer requests, 293 
opening for device functions, 289 
opening multiple times, 293 
opening, 289 
time alarms, 292 
time arithmetic functions, 295 
time delays, 292 
time requests, 287 
units, 288 
uses of time arithmetic, 296 
TimerBase Variable, 289 
Timer_Arithmetic.c, 295 
Trackdisk Device, 303 
adding an interrupt handler, 314 
additional information, 322 
byte offset calculation, 307 
clearing the track buffer, 310 
closing, 308 
commands and functions, 304 
controlling the drive motor, 310 
determing drive geometry, 309 
determing the diskchange number, 313 
determing write-protect status, 312 
determining drive type, 312 
determining the number of tracks, 312 
determining the presence of a disk, 312 
device interface, 305 
diagnostic commands, 314 
ejecting a disk, 311 


582 Amiga ROM Kernel Reference Manual: Devices 


enhanced commands, 305 
error codes, 317 
floppy disk I/O, 306 
formatting a track, 311 
iotd_Count, 305 
low-level access, 315 
moving the drive head, 314 
notification of disk changes, 314 
opening, 307 
reading raw data, 315 
reading, 307 
removing an interrupt handler, 314 
restrictions, 306 
sector label, 306 
status commands, 311 
updating a track sector, 310 
writing raw data, 316 
writing, 308 
Track_Copy.c, 318 
TransferQ, 206 
dithering, 206 
Translator Library, 134 
example fragment, 134 
TR_GETSYSTIME command, 290 
TR_SETSYSTIME Command, 290 
Using a Device, 3 
utility.library, 290, 325 
V36_Device_Use.c, 10 
VBLANK Timer Unit, 288 
Vertical Blank Frequency 
find current VB frequency, 92 
WaitO, 6, 18, 270 
WAITECLOCK Timer Unit, 288 
WaitIOO, 6, 7 
WaitPort(, 6, 18 
WAITUNTIL Timer Unit, 288 
Window structure, 66 


Amiga Programmin 
; : : THIRD EDITION 
sh lea AMIGA ROM Kernel 
oes ole NE 
DEVICES 


a Amiga computers are exciting high-performance 
A A id ° ° microcomputers with superb graphics, sound, 
multiwindow and multitasking capabilities. Their 


technologically advanced hardware is designed around 
SF oS a, < the Motorola 68000 microprocessor family and 


sophisticated custom chips. The Amiga's unique system 
software provides programmers with unparalleled 
power, flexibility, and convenience in designing and 
creating programs. 
EES LS LIS EE CS a ee ee A ee eee 
Written by the technical experts at Commodore-Amiga, Inc., who design the Amiga hardware 
and system software, the Amiga® ROM Kernel Reference Manual: Devices presents tutorials and 
detailed examples showing how to use the Amiga's system device interfaces. This new edition 
has been completely revised and updated for Release 2, the latest version of the Amiga's 
operating system. It includes: 


* A comprehensive introductory section for the novice device programmer 

° Complete coverage of all the Amiga's system devices with new information on the 
enhanced Clipboard, Console, Keyboard, Timer, and Trackdisk devices 

° Expanded coverage of Amiga Resources and a new section on the SCSI device 

¢ Acomplete listing of the IFF (Interchange File Format) specification 


For the serious programmer who wants to take full advantage of the Amiga's impressive 
features, the Amiga ROM Kernel Reference Manual: Devices is an indispensable source of 
information on how to use the advanced I/O capabilities of the whole family of Amiga 
oven ele reece 


The AMIGA TECHNICAL REFERENCE SERIES has been revised and updated to provide a 
comprehensive reference and tutorial for the entire line of Amiga computers and for Release 2 of 
the operating system. Other titles in the series include: 


Amiga User Interface Style Guide 

Amiga ROM Kernel Reference Manual: Includes and Autodocs, Third Edition 
Amiga ROM Kernel Reference Manual: Libraries, Third Edition 

Amiga ROM Kernel Hardware Reference Manual, Third Edition 


PPT | nT 


9 "780201 "567755 | 
ISBN O-201-5b6775-X 
Addison-Wesley Publishing Company, Inc. sb??s 


Cover design by Hannus Design Associates 








as brought to you 
from the archives of 


http://retro-commodore.eu